<!doctype html><html class="use-motion" lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"><meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1"><meta http-equiv="Cache-Control" content="no-transform"><meta http-equiv="Cache-Control" content="no-siteapp"><meta name="google-site-verification" content="0axhmy0-lA3xPbR8wPgyWlMZjwWSCfagKukdyeCQ7LU"><link href="/lib/fancybox/source/jquery.fancybox.css?v=2.1.5" rel="stylesheet" type="text/css"><link href="/lib/font-awesome/css/font-awesome.min.css?v=4.6.2" rel="stylesheet" type="text/css"><link href="/css/main.css?v=5.1.0" rel="stylesheet" type="text/css"><meta name="keywords" content="OVN,OVS,SDN,OpenvSwitch,Network"><link rel="alternate" href="/atom.xml" title="赵占旭的博客" type="application/atom+xml"><link rel="shortcut icon" type="image/x-icon" href="/favicon.ico?v=5.1.0"><meta name="description" content="前面我们介绍到ovn-northd服务主要是将Northbound DB存储的逻辑拓扑翻译为chassis和Logical Flow，今天我们从代码的角度看一下他是怎么实现的。"><meta name="keywords" content="OVN,OVS,SDN,OpenvSwitch,Network"><meta property="og:type" content="article"><meta property="og:title" content="OVN Northd服务工作"><meta property="og:url" content="http://zhaozhanxu.com/2017/03/04/SDN/OVN/2017-03-04-ovn-northd/index.html"><meta property="og:site_name" content="赵占旭的博客"><meta property="og:description" content="前面我们介绍到ovn-northd服务主要是将Northbound DB存储的逻辑拓扑翻译为chassis和Logical Flow，今天我们从代码的角度看一下他是怎么实现的。"><meta property="og:locale" content="en"><meta property="og:updated_time" content="2017-12-11T14:31:18.941Z"><meta name="twitter:card" content="summary"><meta name="twitter:title" content="OVN Northd服务工作"><meta name="twitter:description" content="前面我们介绍到ovn-northd服务主要是将Northbound DB存储的逻辑拓扑翻译为chassis和Logical Flow，今天我们从代码的角度看一下他是怎么实现的。"><script type="text/javascript" id="hexo.configurations">var NexT=window.NexT||{},CONFIG={root:"/",sidebar:{position:"left",display:"post",offset:342,offset_float:0},fancybox:!0,motion:!0}</script><link rel="canonical" href="http://zhaozhanxu.com/2017/03/04/SDN/OVN/2017-03-04-ovn-northd/"><title> OVN Northd服务工作 | 赵占旭的博客</title></head><body itemscope itemtype="http://schema.org/WebPage" lang="en"><script>!function(e,a,t,c,n,g,o){e.GoogleAnalyticsObject="ga",e.ga=e.ga||function(){(e.ga.q=e.ga.q||[]).push(arguments)},e.ga.l=1*new Date,g=a.createElement("script"),o=a.getElementsByTagName("script")[0],g.async=1,g.src="//www.google-analytics.com/analytics.js",o.parentNode.insertBefore(g,o)}(window,document),ga("create","3a235f2280210fdd34cebc8c3647e5b8","auto"),ga("send","pageview")</script><script type="text/javascript">var _hmt=_hmt||[];!function(){var e=document.createElement("script");e.src="//hm.baidu.com/hm.js?UA-90327054-1";var t=document.getElementsByTagName("script")[0];t.parentNode.insertBefore(e,t)}()</script><script type="text/javascript">!function(){var e=document.createElement("script");e.src="//tajs.qq.com/stats?sId=60806179";var t=document.getElementsByTagName("script")[0];t.parentNode.insertBefore(e,t)}()</script><div class="container one-collumn sidebar-position-left page-post-detail"><div class="headband"></div><header id="header" class="header" itemscope itemtype="http://schema.org/WPHeader" style="background-image:url(/images/public/home_bg.jpg)"><div class="header-cover"><div class="header-inner"><a class="site-home" href="/">赵占旭的博客</a><div class="site-meta"><div class="custom-logo-site-title"><div href="/" class="brand"><span class="logo-line-before"><i></i></span> <span class="site-title">赵占旭的博客</span><span class="logo-line-after"><i></i></span></div></div><h1 class="site-subtitle" itemprop="description">一花一世界 一叶一菩提</h1></div><div class="site-nav-toggle"> <button><span class="btn-bar"></span><span class="btn-bar"></span><span class="btn-bar"></span></button></div><nav class="site-nav"><ul id="menu" class="menu"><li class="menu-item menu-item-categories"><a href="/categories" rel="section"><i class="menu-item-icon fa fa-fw fa-th"></i><br> Categories</a></li><li class="menu-item menu-item-tags"><a href="/tags" rel="section"><i class="menu-item-icon fa fa-fw fa-tags"></i><br> Tags</a></li><li class="menu-item menu-item-archives"><a href="/archives" rel="section"><i class="menu-item-icon fa fa-fw fa-archive"></i><br> Archives</a></li><li class="menu-item menu-item-about"><a href="/about" rel="section"><i class="menu-item-icon fa fa-fw fa-user"></i><br> About</a></li><li class="menu-item menu-item-search"><a href="javascript:" ; class="popup-trigger"><i class="menu-item-icon fa fa-search fa-fw"></i><br> Search</a></li></ul><div class="site-search"><div class="popup local-search-popup"><div class="local-search-header clearfix"><span class="search-icon"><i class="fa fa-search"></i></span><span class="popup-btn-close"><i class="fa fa-times-circle"></i></span><div class="local-search-input-wrapper"> <input autocapitalize="off" autocomplete="off" autocorrect="off" placeholder="search.placeholder" spellcheck="false" type="text" id="local-search-input"></div></div><div id="local-search-result"></div></div></div></nav></div><div class="header-post"><div class="post-header"><div class="tags"> <a href="/tags/OVS/" rel="tag" title="OVS">OVS</a> <a href="/tags/Network/" rel="tag" title="Network">Network</a> <a href="/tags/SDN/" rel="tag" title="SDN">SDN</a> <a href="/tags/OVN/" rel="tag" title="OVN">OVN</a></div><h1>OVN Northd服务工作</h1><h2 class="subtitle">Section 5. Northd 服务怎么将Nb DB翻译为Sb DB</h2><div class="post-time"> <span class="post-meta-item-text">Posted on</span> <time itemprop="dateCreated" datetime="2017-03-04T00:00:00+08:00" content="2017-03-04" title="2017-03-04 00:00:00">2017-03-04</time></div></div></div></div></header><main id="main" class="main"><div class="main-inner"><div class="content-wrap"><div id="content" class="content"><div id="posts" class="posts-expand"><article class="post post-type-normal" itemscope itemtype="http://schema.org/Article"><link itemprop="mainEntityOfPage" href="http://zhaozhanxu.com/2017/03/04/SDN/OVN/2017-03-04-ovn-northd/"><span style="display:none" itemprop="author" itemscope itemtype="http://schema.org/Person"><meta itemprop="name" content="赵占旭"><meta itemprop="description" content=""><meta itemprop="image" content="/images/public/me.jpg"></span><span style="display:none" itemprop="publisher" itemscope itemtype="http://schema.org/Organization"><meta itemprop="name" content="赵占旭的博客"> <span style="display:none" itemprop="logo" itemscope itemtype="http://schema.org/ImageObject"><img style="display:none" itemprop="url image" alt="赵占旭的博客" src=""></span></span><div class="post-inner"><header class="post-header"><h2 class="post-title" itemprop="name headline"> OVN Northd服务工作</h2><div class="post-meta"><span class="post-time"><span class="post-meta-item-icon"><i class="fa fa-calendar-o"></i></span> <span class="post-meta-item-text">Posted on</span> <time title="Post created" itemprop="dateCreated datePublished" datetime="2017-03-04T00:00:00+08:00">2017-03-04</time></span></div></header><div class="post-info"><div class="post-categories"> <a class="color" href="/categories/OVN/" rel="tag">OVN</a></div><div class="post-tags"> <a class="color" href="/tags/OVS/" rel="tag">OVS</a> <a class="color" href="/tags/Network/" rel="tag">Network</a> <a class="color" href="/tags/SDN/" rel="tag">SDN</a> <a class="color" href="/tags/OVN/" rel="tag">OVN</a></div><div class="clearfix"></div></div><div class="post-body" itemprop="articleBody"><p>前面我们介绍到ovn-northd服务主要是将Northbound DB存储的逻辑拓扑翻译为chassis和Logical Flow，今天我们从代码的角度看一下他是怎么实现的。</p><a id="more"></a><p>最近发现了一篇不错的文章，点击这里查看<a href="http://networkop.co.uk/blog/2016/11/27/ovn-part1/" target="_blank" rel="noopener">part 1</a>和<a href="http://networkop.co.uk/blog/2016/12/10/ovn-part2/" target="_blank" rel="noopener">part 2</a>。</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">(<span class="keyword">int</span> argc, <span class="keyword">char</span> *argv[])</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="comment">//创建到nb db的连接，连接维护的数据记录在ovn-nb.ovsschema</span></span><br><span class="line">    <span class="comment">//注意函数ovsdb_idl_create的第三个参数，表示默认监控所有更新</span></span><br><span class="line">    <span class="class"><span class="keyword">struct</span> <span class="title">ovsdb_idl_loop</span> <span class="title">ovnnb_idl_loop</span> = <span class="title">OVSDB_IDL_LOOP_INITIALIZER</span>(</span></span><br><span class="line"><span class="class">                <span class="title">ovsdb_idl_create</span>(<span class="title">ovnnb_db</span>, &amp;<span class="title">nbrec_idl_class</span>, <span class="title">true</span>, <span class="title">true</span>));</span></span><br><span class="line">    <span class="comment">//I think... maybe... 分别忽略sb和hv配置更新的提示</span></span><br><span class="line">    ovsdb_idl_omit_alert(ovnnb_idl_loop.idl, &amp;nbrec_nb_global_col_sb_cfg);</span><br><span class="line">    ovsdb_idl_omit_alert(ovnnb_idl_loop.idl, &amp;nbrec_nb_global_col_hv_cfg);</span><br><span class="line"></span><br><span class="line">    <span class="comment">//创建到sb db的连接，连接维护的数据记录在ovn-sb.ovsschema</span></span><br><span class="line">    <span class="comment">//注意函数ovsdb_idl_create的第三个参数，表示默认都不管</span></span><br><span class="line">    <span class="class"><span class="keyword">struct</span> <span class="title">ovsdb_idl_loop</span> <span class="title">ovnsb_idl_loop</span> = <span class="title">OVSDB_IDL_LOOP_INITIALIZER</span>(</span></span><br><span class="line"><span class="class">                <span class="title">ovsdb_idl_create</span>(<span class="title">ovnsb_db</span>, &amp;<span class="title">sbrec_idl_class</span>, <span class="title">false</span>, <span class="title">true</span>));</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">//当上面的ovsdb_idl_create的第三个参数是false的时候，需要调用这个接口</span></span><br><span class="line">    <span class="comment">//用来确认带有sbrec_table_sb_global的类会被复制</span></span><br><span class="line">    ovsdb_idl_add_table(ovnsb_idl_loop.idl, &amp;sbrec_table_sb_global);</span><br><span class="line">    <span class="comment">//用来确认带有sbrec_sb_global_col_nb_cfg的列会被复制，不提示</span></span><br><span class="line">    add_column_noalert(ovnsb_idl_loop.idl, &amp;sbrec_sb_global_col_nb_cfg);</span><br><span class="line"></span><br><span class="line">    <span class="comment">//确认Logical Flow表会被复制，确认该表里面的datapath、</span></span><br><span class="line">    <span class="comment">//pipeline、table_id、match、action会被复制并且不提示。</span></span><br><span class="line">    <span class="comment">//以下这些操作都是类似这里的操作，至于这些表和col可以参照前面介绍。</span></span><br><span class="line">    ovsdb_idl_add_table(ovnsb_idl_loop.idl, &amp;sbrec_table_logical_flow);</span><br><span class="line">    add_column_noalert(ovnsb_idl_loop.idl,</span><br><span class="line">                &amp;sbrec_logical_flow_col_logical_datapath);</span><br><span class="line">    add_column_noalert(ovnsb_idl_loop.idl, &amp;sbrec_logical_flow_col_pipeline);</span><br><span class="line">    add_column_noalert(ovnsb_idl_loop.idl, &amp;sbrec_logical_flow_col_table_id);</span><br><span class="line">    add_column_noalert(ovnsb_idl_loop.idl, &amp;sbrec_logical_flow_col_match);</span><br><span class="line">    add_column_noalert(ovnsb_idl_loop.idl, &amp;sbrec_logical_flow_col_actions);</span><br><span class="line"></span><br><span class="line">    ovsdb_idl_add_table(ovnsb_idl_loop.idl, &amp;sbrec_table_multicast_group);</span><br><span class="line">    add_column_noalert(ovnsb_idl_loop.idl,</span><br><span class="line">                &amp;sbrec_multicast_group_col_datapath);</span><br><span class="line">    add_column_noalert(ovnsb_idl_loop.idl,</span><br><span class="line">                &amp;sbrec_multicast_group_col_tunnel_key);</span><br><span class="line">    add_column_noalert(ovnsb_idl_loop.idl, &amp;sbrec_multicast_group_col_name);</span><br><span class="line">    add_column_noalert(ovnsb_idl_loop.idl, &amp;sbrec_multicast_group_col_ports);</span><br><span class="line"></span><br><span class="line">    ovsdb_idl_add_table(ovnsb_idl_loop.idl, &amp;sbrec_table_datapath_binding);</span><br><span class="line">    add_column_noalert(ovnsb_idl_loop.idl,</span><br><span class="line">                &amp;sbrec_datapath_binding_col_tunnel_key);</span><br><span class="line">    add_column_noalert(ovnsb_idl_loop.idl,</span><br><span class="line">                &amp;sbrec_datapath_binding_col_external_ids);</span><br><span class="line"></span><br><span class="line">    ovsdb_idl_add_table(ovnsb_idl_loop.idl, &amp;sbrec_table_port_binding);</span><br><span class="line">    add_column_noalert(ovnsb_idl_loop.idl, &amp;sbrec_port_binding_col_datapath);</span><br><span class="line">    add_column_noalert(ovnsb_idl_loop.idl,</span><br><span class="line">                &amp;sbrec_port_binding_col_logical_port);</span><br><span class="line">    add_column_noalert(ovnsb_idl_loop.idl,</span><br><span class="line">                &amp;sbrec_port_binding_col_tunnel_key);</span><br><span class="line">    add_column_noalert(ovnsb_idl_loop.idl,</span><br><span class="line">                &amp;sbrec_port_binding_col_parent_port);</span><br><span class="line">    add_column_noalert(ovnsb_idl_loop.idl, &amp;sbrec_port_binding_col_tag);</span><br><span class="line">    add_column_noalert(ovnsb_idl_loop.idl, &amp;sbrec_port_binding_col_type);</span><br><span class="line">    add_column_noalert(ovnsb_idl_loop.idl, &amp;sbrec_port_binding_col_options);</span><br><span class="line">    add_column_noalert(ovnsb_idl_loop.idl, &amp;sbrec_port_binding_col_mac);</span><br><span class="line">    ovsdb_idl_add_column(ovnsb_idl_loop.idl, &amp;sbrec_port_binding_col_chassis);</span><br><span class="line"></span><br><span class="line">    ovsdb_idl_add_table(ovnsb_idl_loop.idl, &amp;sbrec_table_mac_binding);</span><br><span class="line">    add_column_noalert(ovnsb_idl_loop.idl, &amp;sbrec_mac_binding_col_datapath);</span><br><span class="line">    add_column_noalert(ovnsb_idl_loop.idl, &amp;sbrec_mac_binding_col_ip);</span><br><span class="line">    add_column_noalert(ovnsb_idl_loop.idl, &amp;sbrec_mac_binding_col_mac);</span><br><span class="line">    add_column_noalert(ovnsb_idl_loop.idl,</span><br><span class="line">                &amp;sbrec_mac_binding_col_logical_port);</span><br><span class="line"></span><br><span class="line">    ovsdb_idl_add_table(ovnsb_idl_loop.idl, &amp;sbrec_table_dhcp_options);</span><br><span class="line">    add_column_noalert(ovnsb_idl_loop.idl, &amp;sbrec_dhcp_options_col_code);</span><br><span class="line">    add_column_noalert(ovnsb_idl_loop.idl, &amp;sbrec_dhcp_options_col_type);</span><br><span class="line">    add_column_noalert(ovnsb_idl_loop.idl, &amp;sbrec_dhcp_options_col_name);</span><br><span class="line"></span><br><span class="line">    ovsdb_idl_add_table(ovnsb_idl_loop.idl, &amp;sbrec_table_dhcpv6_options);</span><br><span class="line">    add_column_noalert(ovnsb_idl_loop.idl, &amp;sbrec_dhcpv6_options_col_code);</span><br><span class="line">    add_column_noalert(ovnsb_idl_loop.idl, &amp;sbrec_dhcpv6_options_col_type);</span><br><span class="line">    add_column_noalert(ovnsb_idl_loop.idl, &amp;sbrec_dhcpv6_options_col_name);</span><br><span class="line"></span><br><span class="line">    ovsdb_idl_add_table(ovnsb_idl_loop.idl, &amp;sbrec_table_address_set);</span><br><span class="line">    add_column_noalert(ovnsb_idl_loop.idl, &amp;sbrec_address_set_col_name);</span><br><span class="line">    add_column_noalert(ovnsb_idl_loop.idl, &amp;sbrec_address_set_col_addresses);</span><br><span class="line"></span><br><span class="line">    ovsdb_idl_add_table(ovnsb_idl_loop.idl, &amp;sbrec_table_chassis);</span><br><span class="line">    ovsdb_idl_add_column(ovnsb_idl_loop.idl, &amp;sbrec_chassis_col_nb_cfg);</span><br><span class="line"></span><br><span class="line">    <span class="comment">/* Main loop. */</span></span><br><span class="line">    exiting = <span class="literal">false</span>;</span><br><span class="line">    <span class="keyword">while</span> (!exiting) &#123;</span><br><span class="line">        <span class="class"><span class="keyword">struct</span> <span class="title">northd_context</span> <span class="title">ctx</span> = &#123;</span></span><br><span class="line">            .ovnnb_idl = ovnnb_idl_loop.idl,</span><br><span class="line">            <span class="comment">//加载nbdb的数据</span></span><br><span class="line">            .ovnnb_txn = ovsdb_idl_loop_run(&amp;ovnnb_idl_loop),</span><br><span class="line">            .ovnsb_idl = ovnsb_idl_loop.idl,</span><br><span class="line">            <span class="comment">//加载sbdb的数据</span></span><br><span class="line">            .ovnsb_txn = ovsdb_idl_loop_run(&amp;ovnsb_idl_loop),</span><br><span class="line">        &#125;;</span><br><span class="line"></span><br><span class="line">        <span class="comment">//将ctx-&gt;ovnnb_txn的各项数据通过翻译加载到ctx-&gt;ovnsb_txn中</span></span><br><span class="line">        ovnnb_db_run(&amp;ctx, &amp;ovnsb_idl_loop);</span><br><span class="line">        <span class="comment">//主要更新端口信息</span></span><br><span class="line">        ovnsb_db_run(&amp;ctx, &amp;ovnsb_idl_loop);</span><br><span class="line">        <span class="keyword">if</span> (ctx.ovnsb_txn) &#123;</span><br><span class="line">            check_and_add_supported_dhcp_opts_to_sb_db(&amp;ctx);</span><br><span class="line">            check_and_add_supported_dhcpv6_opts_to_sb_db(&amp;ctx);</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="comment">//监听服务，主要是处理各个ovn-controller的连接，通过json rpc的方式通信</span></span><br><span class="line">        unixctl_server_run(unixctl);</span><br><span class="line">        unixctl_server_wait(unixctl);</span><br><span class="line">        <span class="keyword">if</span> (exiting) &#123;</span><br><span class="line">            poll_immediate_wake();</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment">//提交ctx的信息到nbdb和sbdb</span></span><br><span class="line">        ovsdb_idl_loop_commit_and_wait(&amp;ovnnb_idl_loop);</span><br><span class="line">        ovsdb_idl_loop_commit_and_wait(&amp;ovnsb_idl_loop);</span><br><span class="line"></span><br><span class="line">        poll_block();</span><br><span class="line">        <span class="keyword">if</span> (should_service_stop()) &#123;</span><br><span class="line">            exiting = <span class="literal">true</span>;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    unixctl_server_destroy(unixctl);</span><br><span class="line">    ovsdb_idl_loop_destroy(&amp;ovnnb_idl_loop);</span><br><span class="line">    ovsdb_idl_loop_destroy(&amp;ovnsb_idl_loop);</span><br><span class="line">    service_stop();</span><br><span class="line"></span><br><span class="line">    <span class="built_in">exit</span>(res);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">static</span> <span class="keyword">void</span></span><br><span class="line">ovnnb_db_run(struct northd_context *ctx, struct ovsdb_idl_loop *sb_loop)</span><br><span class="line">&#123;</span><br><span class="line">    <span class="comment">//将nbdb数据库中的logical switches、routers和datapath的对应关系</span></span><br><span class="line">    <span class="comment">//更新到sb表Datapath_Binding中，并且存储在struct ovn_datapath</span></span><br><span class="line">    build_datapaths(ctx, &amp;datapaths);</span><br><span class="line">    <span class="comment">//将nbdb数据库中的logical switch ports</span></span><br><span class="line">    <span class="comment">//更新到sb表Port_Binding中，并且存储在struct ovn_port</span></span><br><span class="line">    build_ports(ctx, &amp;datapaths, &amp;ports);</span><br><span class="line">    <span class="comment">//用来创建管理IP和MAC的表，比如配置了IP或者dynamic以及MAC时</span></span><br><span class="line">    build_ipam(&amp;datapaths, &amp;ports);</span><br><span class="line">    <span class="comment">//基于nbdb的内容生成的Logical_Flow和Multicast_Group</span></span><br><span class="line">    <span class="comment">//生成的各级流表前面一篇文章都有介绍</span></span><br><span class="line">    build_lflows(ctx, &amp;datapaths, &amp;ports);</span><br><span class="line"></span><br><span class="line">    <span class="comment">//Address_Set表更新</span></span><br><span class="line">    sync_address_sets(ctx);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">static</span> <span class="keyword">void</span></span><br><span class="line">ovnsb_db_run(struct northd_context *ctx, struct ovsdb_idl_loop *sb_loop)</span><br><span class="line">&#123;</span><br><span class="line">    <span class="keyword">if</span> (!ctx-&gt;ovnnb_txn || !ovsdb_idl_has_ever_connected(ctx-&gt;ovnsb_idl)) &#123;</span><br><span class="line">        <span class="keyword">return</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">//更新Port_Binding表chassis列，不为空时意味着nbdb中将这个端口设置为UP</span></span><br><span class="line">    update_logical_port_status(ctx);</span><br><span class="line">    update_northbound_cfg(ctx, sb_loop);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>Datapath_Binding、Port_Binding、MAC_Binding的创建都还比较简单，所以就不看了，主要看一下逻辑流表的生成，首先会创建逻辑交换网元的逻辑流表，然后创建逻辑路由网元的逻辑流表，最后会查看目前的逻辑流表，然后对比变化，将更改的逻辑流表写入数据库中，我们重点关注一下逻辑交换和逻辑路由两个网元的逻辑流表。</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br><span class="line">167</span><br><span class="line">168</span><br><span class="line">169</span><br><span class="line">170</span><br><span class="line">171</span><br><span class="line">172</span><br><span class="line">173</span><br><span class="line">174</span><br><span class="line">175</span><br><span class="line">176</span><br><span class="line">177</span><br><span class="line">178</span><br><span class="line">179</span><br><span class="line">180</span><br><span class="line">181</span><br><span class="line">182</span><br><span class="line">183</span><br><span class="line">184</span><br><span class="line">185</span><br><span class="line">186</span><br><span class="line">187</span><br><span class="line">188</span><br><span class="line">189</span><br><span class="line">190</span><br><span class="line">191</span><br><span class="line">192</span><br><span class="line">193</span><br><span class="line">194</span><br><span class="line">195</span><br><span class="line">196</span><br><span class="line">197</span><br><span class="line">198</span><br><span class="line">199</span><br><span class="line">200</span><br><span class="line">201</span><br><span class="line">202</span><br><span class="line">203</span><br><span class="line">204</span><br><span class="line">205</span><br><span class="line">206</span><br><span class="line">207</span><br><span class="line">208</span><br><span class="line">209</span><br><span class="line">210</span><br><span class="line">211</span><br><span class="line">212</span><br><span class="line">213</span><br><span class="line">214</span><br><span class="line">215</span><br><span class="line">216</span><br><span class="line">217</span><br><span class="line">218</span><br><span class="line">219</span><br><span class="line">220</span><br><span class="line">221</span><br><span class="line">222</span><br><span class="line">223</span><br><span class="line">224</span><br><span class="line">225</span><br><span class="line">226</span><br><span class="line">227</span><br><span class="line">228</span><br><span class="line">229</span><br><span class="line">230</span><br><span class="line">231</span><br><span class="line">232</span><br><span class="line">233</span><br><span class="line">234</span><br><span class="line">235</span><br><span class="line">236</span><br><span class="line">237</span><br><span class="line">238</span><br><span class="line">239</span><br><span class="line">240</span><br><span class="line">241</span><br><span class="line">242</span><br><span class="line">243</span><br><span class="line">244</span><br><span class="line">245</span><br><span class="line">246</span><br><span class="line">247</span><br><span class="line">248</span><br><span class="line">249</span><br><span class="line">250</span><br><span class="line">251</span><br><span class="line">252</span><br><span class="line">253</span><br><span class="line">254</span><br><span class="line">255</span><br><span class="line">256</span><br><span class="line">257</span><br><span class="line">258</span><br><span class="line">259</span><br><span class="line">260</span><br><span class="line">261</span><br><span class="line">262</span><br><span class="line">263</span><br><span class="line">264</span><br><span class="line">265</span><br><span class="line">266</span><br><span class="line">267</span><br><span class="line">268</span><br><span class="line">269</span><br><span class="line">270</span><br><span class="line">271</span><br><span class="line">272</span><br><span class="line">273</span><br><span class="line">274</span><br><span class="line">275</span><br><span class="line">276</span><br><span class="line">277</span><br><span class="line">278</span><br><span class="line">279</span><br><span class="line">280</span><br><span class="line">281</span><br><span class="line">282</span><br><span class="line">283</span><br><span class="line">284</span><br><span class="line">285</span><br><span class="line">286</span><br><span class="line">287</span><br><span class="line">288</span><br><span class="line">289</span><br><span class="line">290</span><br><span class="line">291</span><br><span class="line">292</span><br><span class="line">293</span><br><span class="line">294</span><br><span class="line">295</span><br><span class="line">296</span><br><span class="line">297</span><br><span class="line">298</span><br><span class="line">299</span><br><span class="line">300</span><br><span class="line">301</span><br><span class="line">302</span><br><span class="line">303</span><br><span class="line">304</span><br><span class="line">305</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">static</span> <span class="keyword">void</span></span><br><span class="line">build_lswitch_flows(struct hmap *datapaths, struct hmap *ports,</span><br><span class="line">                    struct hmap *lflows, struct hmap *mcgroups)</span><br><span class="line">&#123;</span><br><span class="line">    <span class="comment">//创建ingress和egress的pre-ACL和ACL表，对应着ingress的表3-9和egress的0-6</span></span><br><span class="line">    <span class="comment">//这里面的每个逻辑都和下面类似，我们就不每个都细看了</span></span><br><span class="line">    <span class="class"><span class="keyword">struct</span> <span class="title">ovn_datapath</span> *<span class="title">od</span>;</span></span><br><span class="line">    HMAP_FOR_EACH (od, key_node, datapaths) &#123;</span><br><span class="line">        build_pre_acls(od, lflows);</span><br><span class="line">        build_pre_lb(od, lflows);</span><br><span class="line">        build_pre_stateful(od, lflows);</span><br><span class="line">        build_acls(od, lflows);</span><br><span class="line">        build_flows(od, lflows);</span><br><span class="line">        build_qos(od, lflows);</span><br><span class="line">        build_lb(od, lflows);</span><br><span class="line">        build_stateful(od, lflows);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">//ingress 表0 100优先级的入口控制</span></span><br><span class="line">    HMAP_FOR_EACH (od, key_node, datapaths) &#123;</span><br><span class="line">        <span class="comment">//带VLAN标签的报文丢弃</span></span><br><span class="line">        ovn_lflow_add(lflows, od, S_SWITCH_IN_PORT_SEC_L2, <span class="number">100</span>, <span class="string">"vlan.present"</span>,</span><br><span class="line">                      <span class="string">"drop;"</span>);</span><br><span class="line">        <span class="comment">//源地址多播或者广播的报文丢弃</span></span><br><span class="line">        ovn_lflow_add(lflows, od, S_SWITCH_IN_PORT_SEC_L2, <span class="number">100</span>, <span class="string">"eth.src[40]"</span>,</span><br><span class="line">                      <span class="string">"drop;"</span>);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">//ingress 表0 50优先级的端口安全控制</span></span><br><span class="line">    <span class="class"><span class="keyword">struct</span> <span class="title">ovn_port</span> *<span class="title">op</span>;</span></span><br><span class="line">    HMAP_FOR_EACH (op, key_node, ports) &#123;</span><br><span class="line">        ds_put_format(&amp;match, <span class="string">"inport == %s"</span>, op-&gt;json_key);</span><br><span class="line">        build_port_security_l2(<span class="string">"eth.src"</span>, op-&gt;ps_addrs, op-&gt;n_ps_addrs,</span><br><span class="line">                               &amp;match);</span><br><span class="line"></span><br><span class="line">        <span class="keyword">const</span> <span class="keyword">char</span> *queue_id = smap_get(&amp;op-&gt;sb-&gt;options, <span class="string">"qdisc_queue_id"</span>);</span><br><span class="line">        <span class="keyword">if</span> (queue_id) &#123;</span><br><span class="line">            ds_put_format(&amp;actions, <span class="string">"set_queue(%s); "</span>, queue_id);</span><br><span class="line">        &#125;</span><br><span class="line">        ds_put_cstr(&amp;actions, <span class="string">"next;"</span>);</span><br><span class="line">        <span class="comment">//符合条件的报文通过</span></span><br><span class="line">        ovn_lflow_add(lflows, op-&gt;od, S_SWITCH_IN_PORT_SEC_L2, <span class="number">50</span>,</span><br><span class="line">                      ds_cstr(&amp;match), ds_cstr(&amp;actions));</span><br><span class="line"></span><br><span class="line">        <span class="keyword">if</span> (op-&gt;nbsp-&gt;n_port_security) &#123;</span><br><span class="line">            <span class="comment">//根据IP或者ND的安全配置，确定是否有ingress 表1和2的端口安全设置，优先级80和90</span></span><br><span class="line">            build_port_security_ip(P_IN, op, lflows);</span><br><span class="line">            build_port_security_nd(op, lflows);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">//ingress 表1-2的端口安全默认优先级0的操作是允许通过</span></span><br><span class="line">    HMAP_FOR_EACH (od, key_node, datapaths) &#123;</span><br><span class="line">        ovn_lflow_add(lflows, od, S_SWITCH_IN_PORT_SEC_ND, <span class="number">0</span>, <span class="string">"1"</span>, <span class="string">"next;"</span>);</span><br><span class="line">        ovn_lflow_add(lflows, od, S_SWITCH_IN_PORT_SEC_IP, <span class="number">0</span>, <span class="string">"1"</span>, <span class="string">"next;"</span>);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">//ingress 表10 100优先级，ARP请求，如果是localnet或者vtep的端口则通过</span></span><br><span class="line">    HMAP_FOR_EACH (op, key_node, ports) &#123;</span><br><span class="line">        <span class="keyword">if</span> ((!<span class="built_in">strcmp</span>(op-&gt;nbsp-&gt;type, <span class="string">"localnet"</span>)) ||</span><br><span class="line">            (!<span class="built_in">strcmp</span>(op-&gt;nbsp-&gt;type, <span class="string">"vtep"</span>))) &#123;</span><br><span class="line">            ds_clear(&amp;match);</span><br><span class="line">            ds_put_format(&amp;match, <span class="string">"inport == %s"</span>, op-&gt;json_key);</span><br><span class="line">            ovn_lflow_add(lflows, op-&gt;od, S_SWITCH_IN_ARP_ND_RSP, <span class="number">100</span>,</span><br><span class="line">                          ds_cstr(&amp;match), <span class="string">"next;"</span>);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">//ingress 表10 50优先级 ARP请求，代答已知的IP</span></span><br><span class="line">    HMAP_FOR_EACH (op, key_node, ports) &#123;</span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">size_t</span> i = <span class="number">0</span>; i &lt; op-&gt;n_lsp_addrs; i++) &#123;</span><br><span class="line">            <span class="keyword">for</span> (<span class="keyword">size_t</span> j = <span class="number">0</span>; j &lt; op-&gt;lsp_addrs[i].n_ipv4_addrs; j++) &#123;</span><br><span class="line">                ds_clear(&amp;match);</span><br><span class="line">                ds_put_format(&amp;match, <span class="string">"arp.tpa == %s &amp;&amp; arp.op == 1"</span>,</span><br><span class="line">                              op-&gt;lsp_addrs[i].ipv4_addrs[j].addr_s);</span><br><span class="line">                ds_clear(&amp;actions);</span><br><span class="line">                ds_put_format(&amp;actions,</span><br><span class="line">                    <span class="string">"eth.dst = eth.src; "</span></span><br><span class="line">                    <span class="string">"eth.src = %s; "</span></span><br><span class="line">                    <span class="string">"arp.op = 2; /* ARP reply */ "</span></span><br><span class="line">                    <span class="string">"arp.tha = arp.sha; "</span></span><br><span class="line">                    <span class="string">"arp.sha = %s; "</span></span><br><span class="line">                    <span class="string">"arp.tpa = arp.spa; "</span></span><br><span class="line">                    <span class="string">"arp.spa = %s; "</span></span><br><span class="line">                    <span class="string">"outport = inport; "</span></span><br><span class="line">                    <span class="string">"flags.loopback = 1; "</span></span><br><span class="line">                    <span class="string">"output;"</span>,</span><br><span class="line">                    op-&gt;lsp_addrs[i].ea_s, op-&gt;lsp_addrs[i].ea_s,</span><br><span class="line">                    op-&gt;lsp_addrs[i].ipv4_addrs[j].addr_s);</span><br><span class="line">                ovn_lflow_add(lflows, op-&gt;od, S_SWITCH_IN_ARP_ND_RSP, <span class="number">50</span>,</span><br><span class="line">                              ds_cstr(&amp;match), ds_cstr(&amp;actions));</span><br><span class="line"></span><br><span class="line">                <span class="comment">//DHCP客户端通过ARP请求判定是否有IP冲突的时候，会请求自己已有的IP地址</span></span><br><span class="line">                <span class="comment">//这个时候不要代答，所以需要判定ARP请求的IP和发送端的IP一致时，通过</span></span><br><span class="line">                ds_put_format(&amp;match, <span class="string">" &amp;&amp; inport == %s"</span>, op-&gt;json_key);</span><br><span class="line">                ovn_lflow_add(lflows, op-&gt;od, S_SWITCH_IN_ARP_ND_RSP, <span class="number">100</span>,</span><br><span class="line">                              ds_cstr(&amp;match), <span class="string">"next;"</span>);</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">//ingress 表10 0优先级，默认通过ARP请求</span></span><br><span class="line">    HMAP_FOR_EACH (od, key_node, datapaths) &#123;</span><br><span class="line">        ovn_lflow_add(lflows, od, S_SWITCH_IN_ARP_ND_RSP, <span class="number">0</span>, <span class="string">"1"</span>, <span class="string">"next;"</span>);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">//ingress 表11-12 100优先级，DHCP options和response操作</span></span><br><span class="line">    HMAP_FOR_EACH (op, key_node, ports) &#123;</span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">size_t</span> i = <span class="number">0</span>; i &lt; op-&gt;n_lsp_addrs; i++) &#123;</span><br><span class="line">            <span class="keyword">for</span> (<span class="keyword">size_t</span> j = <span class="number">0</span>; j &lt; op-&gt;lsp_addrs[i].n_ipv4_addrs; j++) &#123;</span><br><span class="line">                <span class="keyword">if</span> (build_dhcpv4_action(</span><br><span class="line">                        op, op-&gt;lsp_addrs[i].ipv4_addrs[j].addr,</span><br><span class="line">                        &amp;options_action, &amp;response_action, &amp;ipv4_addr_match)) &#123;</span><br><span class="line">                    ds_put_format(</span><br><span class="line">                        &amp;match, <span class="string">"inport == %s &amp;&amp; eth.src == %s &amp;&amp; "</span></span><br><span class="line">                        <span class="string">"ip4.src == 0.0.0.0 &amp;&amp; ip4.dst == 255.255.255.255 &amp;&amp; "</span></span><br><span class="line">                        <span class="string">"udp.src == 68 &amp;&amp; udp.dst == 67"</span>, op-&gt;json_key,</span><br><span class="line">                        op-&gt;lsp_addrs[i].ea_s);</span><br><span class="line"></span><br><span class="line">                    <span class="comment">//修改DHCP报文的option部分，给出分配的IP地址，以及回复信息</span></span><br><span class="line">                    <span class="comment">//然后进入下一级即response</span></span><br><span class="line">                    ovn_lflow_add(lflows, op-&gt;od, S_SWITCH_IN_DHCP_OPTIONS,</span><br><span class="line">                                  <span class="number">100</span>, ds_cstr(&amp;match),</span><br><span class="line">                                  ds_cstr(&amp;options_action));</span><br><span class="line">                    ds_clear(&amp;match);</span><br><span class="line">                    ds_put_format(</span><br><span class="line">                        &amp;match, <span class="string">"inport == %s &amp;&amp; eth.src == %s &amp;&amp; "</span></span><br><span class="line">                        <span class="string">"%s &amp;&amp; udp.src == 68 &amp;&amp; udp.dst == 67"</span>, op-&gt;json_key,</span><br><span class="line">                        op-&gt;lsp_addrs[i].ea_s, ds_cstr(&amp;ipv4_addr_match));</span><br><span class="line"></span><br><span class="line">                    <span class="comment">//当客户端需要renew一个新的IP的时候，需要match项更改如下</span></span><br><span class="line">                    <span class="comment">//ip4.src = OFFER_IP and ip4.dst = &#123;SERVER_IP, 255.255.255.255&#125;</span></span><br><span class="line">                    ovn_lflow_add(lflows, op-&gt;od, S_SWITCH_IN_DHCP_OPTIONS,</span><br><span class="line">                                  <span class="number">100</span>, ds_cstr(&amp;match),</span><br><span class="line">                                  ds_cstr(&amp;options_action));</span><br><span class="line">                    ds_clear(&amp;match);</span><br><span class="line"></span><br><span class="line">                    ds_put_format(</span><br><span class="line">                        &amp;match, <span class="string">"inport == %s &amp;&amp; eth.src == %s &amp;&amp; "</span></span><br><span class="line">                        <span class="string">"ip4 &amp;&amp; udp.src == 68 &amp;&amp; udp.dst == 67"</span></span><br><span class="line">                        <span class="string">" &amp;&amp; "</span>REGBIT_DHCP_OPTS_RESULT, op-&gt;json_key,</span><br><span class="line">                        op-&gt;lsp_addrs[i].ea_s);</span><br><span class="line">                    <span class="comment">//如果option已经修改，则修改报文的源目的，变成回复报文</span></span><br><span class="line">                    ovn_lflow_add(lflows, op-&gt;od, S_SWITCH_IN_DHCP_RESPONSE,</span><br><span class="line">                                  <span class="number">100</span>, ds_cstr(&amp;match),</span><br><span class="line">                                  ds_cstr(&amp;response_action));</span><br><span class="line">                    ds_destroy(&amp;match);</span><br><span class="line">                    ds_destroy(&amp;options_action);</span><br><span class="line">                    ds_destroy(&amp;response_action);</span><br><span class="line">                    ds_destroy(&amp;ipv4_addr_match);</span><br><span class="line">                    <span class="keyword">break</span>;</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">//ingress 表11-12 0优先级，默认通过</span></span><br><span class="line">    HMAP_FOR_EACH (od, key_node, datapaths) &#123;</span><br><span class="line">        ovn_lflow_add(lflows, od, S_SWITCH_IN_DHCP_OPTIONS, <span class="number">0</span>, <span class="string">"1"</span>, <span class="string">"next;"</span>);</span><br><span class="line">        ovn_lflow_add(lflows, od, S_SWITCH_IN_DHCP_RESPONSE, <span class="number">0</span>, <span class="string">"1"</span>, <span class="string">"next;"</span>);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">//ingress 表13 100优先级，多播广播flood</span></span><br><span class="line">    HMAP_FOR_EACH (op, key_node, ports) &#123;</span><br><span class="line">        <span class="keyword">if</span> (lsp_is_enabled(op-&gt;nbsp)) &#123;</span><br><span class="line">            ovn_multicast_add(mcgroups, &amp;mc_flood, op);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    HMAP_FOR_EACH (od, key_node, datapaths) &#123;</span><br><span class="line">        ovn_lflow_add(lflows, od, S_SWITCH_IN_L2_LKUP, <span class="number">100</span>, <span class="string">"eth.mcast"</span>,</span><br><span class="line">                      <span class="string">"outport = \""</span>MC_FLOOD<span class="string">"\"; output;"</span>);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">//ingress 表13, 50优先级，根据目的MAC查找出口</span></span><br><span class="line">    <span class="comment">//逻辑交换的逻辑端口本来应该没有MAC地址，都是记录的对端的MAC</span></span><br><span class="line">    HMAP_FOR_EACH (op, key_node, ports) &#123;</span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">size_t</span> i = <span class="number">0</span>; i &lt; op-&gt;nbsp-&gt;n_addresses; i++) &#123;</span><br><span class="line">            <span class="class"><span class="keyword">struct</span> <span class="title">eth_addr</span> <span class="title">mac</span>;</span></span><br><span class="line">            <span class="comment">//将逻辑交换的逻辑端口MAC地址进行格式转换，然后写到match里面</span></span><br><span class="line">            <span class="keyword">if</span> (ovs_scan(op-&gt;nbsp-&gt;addresses[i],</span><br><span class="line">                        ETH_ADDR_SCAN_FMT, ETH_ADDR_SCAN_ARGS(mac))) &#123;</span><br><span class="line">                ds_clear(&amp;match);</span><br><span class="line">                ds_put_format(&amp;match, <span class="string">"eth.dst == "</span>ETH_ADDR_FMT,</span><br><span class="line">                              ETH_ADDR_ARGS(mac));</span><br><span class="line"></span><br><span class="line">                ds_clear(&amp;actions);</span><br><span class="line">                ds_put_format(&amp;actions, <span class="string">"outport = %s; output;"</span>, op-&gt;json_key);</span><br><span class="line">                ovn_lflow_add(lflows, op-&gt;od, S_SWITCH_IN_L2_LKUP, <span class="number">50</span>,</span><br><span class="line">                              ds_cstr(&amp;match), ds_cstr(&amp;actions));</span><br><span class="line">            <span class="comment">//unkown...</span></span><br><span class="line">            &#125; <span class="keyword">else</span> <span class="keyword">if</span> (!<span class="built_in">strcmp</span>(op-&gt;nbsp-&gt;addresses[i], <span class="string">"unknown"</span>)) &#123;</span><br><span class="line">                <span class="keyword">if</span> (lsp_is_enabled(op-&gt;nbsp)) &#123;</span><br><span class="line">                    ovn_multicast_add(mcgroups, &amp;mc_unknown, op);</span><br><span class="line">                    op-&gt;od-&gt;has_unknown = <span class="literal">true</span>;</span><br><span class="line">                &#125;</span><br><span class="line">            <span class="comment">//动态地址的MAC转换，需要从dynamic_addresses</span></span><br><span class="line">            &#125; <span class="keyword">else</span> <span class="keyword">if</span> (is_dynamic_lsp_address(op-&gt;nbsp-&gt;addresses[i])) &#123;</span><br><span class="line">                <span class="keyword">if</span> (!op-&gt;nbsp-&gt;dynamic_addresses</span><br><span class="line">                    || !ovs_scan(op-&gt;nbsp-&gt;dynamic_addresses,</span><br><span class="line">                            ETH_ADDR_SCAN_FMT, ETH_ADDR_SCAN_ARGS(mac))) &#123;</span><br><span class="line">                    <span class="keyword">continue</span>;</span><br><span class="line">                &#125;</span><br><span class="line">                ds_clear(&amp;match);</span><br><span class="line">                ds_put_format(&amp;match, <span class="string">"eth.dst == "</span>ETH_ADDR_FMT,</span><br><span class="line">                              ETH_ADDR_ARGS(mac));</span><br><span class="line"></span><br><span class="line">                ds_clear(&amp;actions);</span><br><span class="line">                ds_put_format(&amp;actions, <span class="string">"outport = %s; output;"</span>, op-&gt;json_key);</span><br><span class="line">                ovn_lflow_add(lflows, op-&gt;od, S_SWITCH_IN_L2_LKUP, <span class="number">50</span>,</span><br><span class="line">                              ds_cstr(&amp;match), ds_cstr(&amp;actions));</span><br><span class="line">            <span class="comment">//router的时候，根据peer的MAC地址进行转换</span></span><br><span class="line">            &#125; <span class="keyword">else</span> <span class="keyword">if</span> (!<span class="built_in">strcmp</span>(op-&gt;nbsp-&gt;addresses[i], <span class="string">"router"</span>)) &#123;</span><br><span class="line">                <span class="keyword">if</span> (!op-&gt;peer || !op-&gt;peer-&gt;nbrp</span><br><span class="line">                    || !ovs_scan(op-&gt;peer-&gt;nbrp-&gt;mac,</span><br><span class="line">                            ETH_ADDR_SCAN_FMT, ETH_ADDR_SCAN_ARGS(mac))) &#123;</span><br><span class="line">                    <span class="keyword">continue</span>;</span><br><span class="line">                &#125;</span><br><span class="line">                ds_clear(&amp;match);</span><br><span class="line">                ds_put_format(&amp;match, <span class="string">"eth.dst == "</span>ETH_ADDR_FMT,</span><br><span class="line">                              ETH_ADDR_ARGS(mac));</span><br><span class="line">                <span class="keyword">if</span> (op-&gt;peer-&gt;od-&gt;l3dgw_port</span><br><span class="line">                    &amp;&amp; op-&gt;peer == op-&gt;peer-&gt;od-&gt;l3dgw_port</span><br><span class="line">                    &amp;&amp; op-&gt;peer-&gt;od-&gt;l3redirect_port) &#123;</span><br><span class="line">                    <span class="comment">//???是不是端口转发，不负责的猜测</span></span><br><span class="line">                    ds_put_format(&amp;match, <span class="string">" &amp;&amp; is_chassis_resident(%s)"</span>,</span><br><span class="line">                                  op-&gt;peer-&gt;od-&gt;l3redirect_port-&gt;json_key);</span><br><span class="line">                &#125;</span><br><span class="line"></span><br><span class="line">                ds_clear(&amp;actions);</span><br><span class="line">                ds_put_format(&amp;actions, <span class="string">"outport = %s; output;"</span>, op-&gt;json_key);</span><br><span class="line">                ovn_lflow_add(lflows, op-&gt;od, S_SWITCH_IN_L2_LKUP, <span class="number">50</span>,</span><br><span class="line">                              ds_cstr(&amp;match), ds_cstr(&amp;actions));</span><br><span class="line"></span><br><span class="line">                <span class="comment">//分布式逻辑路由的NAT规则</span></span><br><span class="line">                <span class="keyword">if</span> (op-&gt;peer-&gt;od-&gt;l3dgw_port</span><br><span class="line">                    &amp;&amp; op-&gt;peer == op-&gt;peer-&gt;od-&gt;l3dgw_port) &#123;</span><br><span class="line">                    <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; op-&gt;peer-&gt;od-&gt;nbr-&gt;n_nat; i++) &#123;</span><br><span class="line">                        <span class="keyword">const</span> <span class="class"><span class="keyword">struct</span> <span class="title">nbrec_nat</span> *<span class="title">nat</span></span></span><br><span class="line"><span class="class">                                                  = <span class="title">op</span>-&gt;<span class="title">peer</span>-&gt;<span class="title">od</span>-&gt;<span class="title">nbr</span>-&gt;<span class="title">nat</span>[<span class="title">i</span>];</span></span><br><span class="line">                        <span class="keyword">if</span> (!<span class="built_in">strcmp</span>(nat-&gt;type, <span class="string">"dnat_and_snat"</span>)</span><br><span class="line">                            &amp;&amp; nat-&gt;logical_port &amp;&amp; nat-&gt;external_mac</span><br><span class="line">                            &amp;&amp; eth_addr_from_string(nat-&gt;external_mac, &amp;mac)) &#123;</span><br><span class="line"></span><br><span class="line">                            ds_clear(&amp;match);</span><br><span class="line">                            ds_put_format(&amp;match, <span class="string">"eth.dst == "</span>ETH_ADDR_FMT</span><br><span class="line">                                          <span class="string">" &amp;&amp; is_chassis_resident(\"%s\")"</span>,</span><br><span class="line">                                          ETH_ADDR_ARGS(mac),</span><br><span class="line">                                          nat-&gt;logical_port);</span><br><span class="line"></span><br><span class="line">                            ds_clear(&amp;actions);</span><br><span class="line">                            ds_put_format(&amp;actions, <span class="string">"outport = %s; output;"</span>,</span><br><span class="line">                                          op-&gt;json_key);</span><br><span class="line">                            ovn_lflow_add(lflows, op-&gt;od, S_SWITCH_IN_L2_LKUP,</span><br><span class="line">                                          <span class="number">50</span>, ds_cstr(&amp;match),</span><br><span class="line">                                          ds_cstr(&amp;actions));</span><br><span class="line">                        &#125;</span><br><span class="line">                    &#125;</span><br><span class="line">                &#125;</span><br><span class="line">            &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                <span class="keyword">static</span> struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(<span class="number">1</span>, <span class="number">1</span>);</span><br><span class="line"></span><br><span class="line">                VLOG_INFO_RL(&amp;rl,</span><br><span class="line">                             <span class="string">"%s: invalid syntax '%s' in addresses column"</span>,</span><br><span class="line">                             op-&gt;nbsp-&gt;name, op-&gt;nbsp-&gt;addresses[i]);</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">//ingress 表13 0优先级，unkown的到哪里了???</span></span><br><span class="line">    HMAP_FOR_EACH (od, key_node, datapaths) &#123;</span><br><span class="line">        <span class="keyword">if</span> (od-&gt;has_unknown) &#123;</span><br><span class="line">            ovn_lflow_add(lflows, od, S_SWITCH_IN_L2_LKUP, <span class="number">0</span>, <span class="string">"1"</span>,</span><br><span class="line">                          <span class="string">"outport = \""</span>MC_UNKNOWN<span class="string">"\"; output;"</span>);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">//egress 表7 0优先级，IP端口安全默认允许过</span></span><br><span class="line">    <span class="comment">//egress 表8 100优先级，多播广播直接发送了</span></span><br><span class="line">    HMAP_FOR_EACH (od, key_node, datapaths) &#123;</span><br><span class="line">        ovn_lflow_add(lflows, od, S_SWITCH_OUT_PORT_SEC_IP, <span class="number">0</span>, <span class="string">"1"</span>, <span class="string">"next;"</span>);</span><br><span class="line">        ovn_lflow_add(lflows, od, S_SWITCH_OUT_PORT_SEC_L2, <span class="number">100</span>, <span class="string">"eth.mcast"</span>,</span><br><span class="line">                      <span class="string">"output;"</span>);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">//egress 表8 50优先级，根据配置设置不允许通过的流量</span></span><br><span class="line">    <span class="comment">//150优先级，丢掉没有使能的逻辑端口的流量</span></span><br><span class="line">    HMAP_FOR_EACH (op, key_node, ports) &#123;</span><br><span class="line">        ds_clear(&amp;match);</span><br><span class="line">        ds_put_format(&amp;match, <span class="string">"outport == %s"</span>, op-&gt;json_key);</span><br><span class="line">        <span class="keyword">if</span> (lsp_is_enabled(op-&gt;nbsp)) &#123;</span><br><span class="line">            build_port_security_l2(<span class="string">"eth.dst"</span>, op-&gt;ps_addrs, op-&gt;n_ps_addrs,</span><br><span class="line">                                   &amp;match);</span><br><span class="line">            ovn_lflow_add(lflows, op-&gt;od, S_SWITCH_OUT_PORT_SEC_L2, <span class="number">50</span>,</span><br><span class="line">                          ds_cstr(&amp;match), <span class="string">"output;"</span>);</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            ovn_lflow_add(lflows, op-&gt;od, S_SWITCH_OUT_PORT_SEC_L2, <span class="number">150</span>,</span><br><span class="line">                          ds_cstr(&amp;match), <span class="string">"drop;"</span>);</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="comment">//egress 表7 80 90优先级，根据配置设置不允许通过流量</span></span><br><span class="line">        <span class="keyword">if</span> (op-&gt;nbsp-&gt;n_port_security) &#123;</span><br><span class="line">            build_port_security_ip(P_OUT, op, lflows);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br><span class="line">167</span><br><span class="line">168</span><br><span class="line">169</span><br><span class="line">170</span><br><span class="line">171</span><br><span class="line">172</span><br><span class="line">173</span><br><span class="line">174</span><br><span class="line">175</span><br><span class="line">176</span><br><span class="line">177</span><br><span class="line">178</span><br><span class="line">179</span><br><span class="line">180</span><br><span class="line">181</span><br><span class="line">182</span><br><span class="line">183</span><br><span class="line">184</span><br><span class="line">185</span><br><span class="line">186</span><br><span class="line">187</span><br><span class="line">188</span><br><span class="line">189</span><br><span class="line">190</span><br><span class="line">191</span><br><span class="line">192</span><br><span class="line">193</span><br><span class="line">194</span><br><span class="line">195</span><br><span class="line">196</span><br><span class="line">197</span><br><span class="line">198</span><br><span class="line">199</span><br><span class="line">200</span><br><span class="line">201</span><br><span class="line">202</span><br><span class="line">203</span><br><span class="line">204</span><br><span class="line">205</span><br><span class="line">206</span><br><span class="line">207</span><br><span class="line">208</span><br><span class="line">209</span><br><span class="line">210</span><br><span class="line">211</span><br><span class="line">212</span><br><span class="line">213</span><br><span class="line">214</span><br><span class="line">215</span><br><span class="line">216</span><br><span class="line">217</span><br><span class="line">218</span><br><span class="line">219</span><br><span class="line">220</span><br><span class="line">221</span><br><span class="line">222</span><br><span class="line">223</span><br><span class="line">224</span><br><span class="line">225</span><br><span class="line">226</span><br><span class="line">227</span><br><span class="line">228</span><br><span class="line">229</span><br><span class="line">230</span><br><span class="line">231</span><br><span class="line">232</span><br><span class="line">233</span><br><span class="line">234</span><br><span class="line">235</span><br><span class="line">236</span><br><span class="line">237</span><br><span class="line">238</span><br><span class="line">239</span><br><span class="line">240</span><br><span class="line">241</span><br><span class="line">242</span><br><span class="line">243</span><br><span class="line">244</span><br><span class="line">245</span><br><span class="line">246</span><br><span class="line">247</span><br><span class="line">248</span><br><span class="line">249</span><br><span class="line">250</span><br><span class="line">251</span><br><span class="line">252</span><br><span class="line">253</span><br><span class="line">254</span><br><span class="line">255</span><br><span class="line">256</span><br><span class="line">257</span><br><span class="line">258</span><br><span class="line">259</span><br><span class="line">260</span><br><span class="line">261</span><br><span class="line">262</span><br><span class="line">263</span><br><span class="line">264</span><br><span class="line">265</span><br><span class="line">266</span><br><span class="line">267</span><br><span class="line">268</span><br><span class="line">269</span><br><span class="line">270</span><br><span class="line">271</span><br><span class="line">272</span><br><span class="line">273</span><br><span class="line">274</span><br><span class="line">275</span><br><span class="line">276</span><br><span class="line">277</span><br><span class="line">278</span><br><span class="line">279</span><br><span class="line">280</span><br><span class="line">281</span><br><span class="line">282</span><br><span class="line">283</span><br><span class="line">284</span><br><span class="line">285</span><br><span class="line">286</span><br><span class="line">287</span><br><span class="line">288</span><br><span class="line">289</span><br><span class="line">290</span><br><span class="line">291</span><br><span class="line">292</span><br><span class="line">293</span><br><span class="line">294</span><br><span class="line">295</span><br><span class="line">296</span><br><span class="line">297</span><br><span class="line">298</span><br><span class="line">299</span><br><span class="line">300</span><br><span class="line">301</span><br><span class="line">302</span><br><span class="line">303</span><br><span class="line">304</span><br><span class="line">305</span><br><span class="line">306</span><br><span class="line">307</span><br><span class="line">308</span><br><span class="line">309</span><br><span class="line">310</span><br><span class="line">311</span><br><span class="line">312</span><br><span class="line">313</span><br><span class="line">314</span><br><span class="line">315</span><br><span class="line">316</span><br><span class="line">317</span><br><span class="line">318</span><br><span class="line">319</span><br><span class="line">320</span><br><span class="line">321</span><br><span class="line">322</span><br><span class="line">323</span><br><span class="line">324</span><br><span class="line">325</span><br><span class="line">326</span><br><span class="line">327</span><br><span class="line">328</span><br><span class="line">329</span><br><span class="line">330</span><br><span class="line">331</span><br><span class="line">332</span><br><span class="line">333</span><br><span class="line">334</span><br><span class="line">335</span><br><span class="line">336</span><br><span class="line">337</span><br><span class="line">338</span><br><span class="line">339</span><br><span class="line">340</span><br><span class="line">341</span><br><span class="line">342</span><br><span class="line">343</span><br><span class="line">344</span><br><span class="line">345</span><br><span class="line">346</span><br><span class="line">347</span><br><span class="line">348</span><br><span class="line">349</span><br><span class="line">350</span><br><span class="line">351</span><br><span class="line">352</span><br><span class="line">353</span><br><span class="line">354</span><br><span class="line">355</span><br><span class="line">356</span><br><span class="line">357</span><br><span class="line">358</span><br><span class="line">359</span><br><span class="line">360</span><br><span class="line">361</span><br><span class="line">362</span><br><span class="line">363</span><br><span class="line">364</span><br><span class="line">365</span><br><span class="line">366</span><br><span class="line">367</span><br><span class="line">368</span><br><span class="line">369</span><br><span class="line">370</span><br><span class="line">371</span><br><span class="line">372</span><br><span class="line">373</span><br><span class="line">374</span><br><span class="line">375</span><br><span class="line">376</span><br><span class="line">377</span><br><span class="line">378</span><br><span class="line">379</span><br><span class="line">380</span><br><span class="line">381</span><br><span class="line">382</span><br><span class="line">383</span><br><span class="line">384</span><br><span class="line">385</span><br><span class="line">386</span><br><span class="line">387</span><br><span class="line">388</span><br><span class="line">389</span><br><span class="line">390</span><br><span class="line">391</span><br><span class="line">392</span><br><span class="line">393</span><br><span class="line">394</span><br><span class="line">395</span><br><span class="line">396</span><br><span class="line">397</span><br><span class="line">398</span><br><span class="line">399</span><br><span class="line">400</span><br><span class="line">401</span><br><span class="line">402</span><br><span class="line">403</span><br><span class="line">404</span><br><span class="line">405</span><br><span class="line">406</span><br><span class="line">407</span><br><span class="line">408</span><br><span class="line">409</span><br><span class="line">410</span><br><span class="line">411</span><br><span class="line">412</span><br><span class="line">413</span><br><span class="line">414</span><br><span class="line">415</span><br><span class="line">416</span><br><span class="line">417</span><br><span class="line">418</span><br><span class="line">419</span><br><span class="line">420</span><br><span class="line">421</span><br><span class="line">422</span><br><span class="line">423</span><br><span class="line">424</span><br><span class="line">425</span><br><span class="line">426</span><br><span class="line">427</span><br><span class="line">428</span><br><span class="line">429</span><br><span class="line">430</span><br><span class="line">431</span><br><span class="line">432</span><br><span class="line">433</span><br><span class="line">434</span><br><span class="line">435</span><br><span class="line">436</span><br><span class="line">437</span><br><span class="line">438</span><br><span class="line">439</span><br><span class="line">440</span><br><span class="line">441</span><br><span class="line">442</span><br><span class="line">443</span><br><span class="line">444</span><br><span class="line">445</span><br><span class="line">446</span><br><span class="line">447</span><br><span class="line">448</span><br><span class="line">449</span><br><span class="line">450</span><br><span class="line">451</span><br><span class="line">452</span><br><span class="line">453</span><br><span class="line">454</span><br><span class="line">455</span><br><span class="line">456</span><br><span class="line">457</span><br><span class="line">458</span><br><span class="line">459</span><br><span class="line">460</span><br><span class="line">461</span><br><span class="line">462</span><br><span class="line">463</span><br><span class="line">464</span><br><span class="line">465</span><br><span class="line">466</span><br><span class="line">467</span><br><span class="line">468</span><br><span class="line">469</span><br><span class="line">470</span><br><span class="line">471</span><br><span class="line">472</span><br><span class="line">473</span><br><span class="line">474</span><br><span class="line">475</span><br><span class="line">476</span><br><span class="line">477</span><br><span class="line">478</span><br><span class="line">479</span><br><span class="line">480</span><br><span class="line">481</span><br><span class="line">482</span><br><span class="line">483</span><br><span class="line">484</span><br><span class="line">485</span><br><span class="line">486</span><br><span class="line">487</span><br><span class="line">488</span><br><span class="line">489</span><br><span class="line">490</span><br><span class="line">491</span><br><span class="line">492</span><br><span class="line">493</span><br><span class="line">494</span><br><span class="line">495</span><br><span class="line">496</span><br><span class="line">497</span><br><span class="line">498</span><br><span class="line">499</span><br><span class="line">500</span><br><span class="line">501</span><br><span class="line">502</span><br><span class="line">503</span><br><span class="line">504</span><br><span class="line">505</span><br><span class="line">506</span><br><span class="line">507</span><br><span class="line">508</span><br><span class="line">509</span><br><span class="line">510</span><br><span class="line">511</span><br><span class="line">512</span><br><span class="line">513</span><br><span class="line">514</span><br><span class="line">515</span><br><span class="line">516</span><br><span class="line">517</span><br><span class="line">518</span><br><span class="line">519</span><br><span class="line">520</span><br><span class="line">521</span><br><span class="line">522</span><br><span class="line">523</span><br><span class="line">524</span><br><span class="line">525</span><br><span class="line">526</span><br><span class="line">527</span><br><span class="line">528</span><br><span class="line">529</span><br><span class="line">530</span><br><span class="line">531</span><br><span class="line">532</span><br><span class="line">533</span><br><span class="line">534</span><br><span class="line">535</span><br><span class="line">536</span><br><span class="line">537</span><br><span class="line">538</span><br><span class="line">539</span><br><span class="line">540</span><br><span class="line">541</span><br><span class="line">542</span><br><span class="line">543</span><br><span class="line">544</span><br><span class="line">545</span><br><span class="line">546</span><br><span class="line">547</span><br><span class="line">548</span><br><span class="line">549</span><br><span class="line">550</span><br><span class="line">551</span><br><span class="line">552</span><br><span class="line">553</span><br><span class="line">554</span><br><span class="line">555</span><br><span class="line">556</span><br><span class="line">557</span><br><span class="line">558</span><br><span class="line">559</span><br><span class="line">560</span><br><span class="line">561</span><br><span class="line">562</span><br><span class="line">563</span><br><span class="line">564</span><br><span class="line">565</span><br><span class="line">566</span><br><span class="line">567</span><br><span class="line">568</span><br><span class="line">569</span><br><span class="line">570</span><br><span class="line">571</span><br><span class="line">572</span><br><span class="line">573</span><br><span class="line">574</span><br><span class="line">575</span><br><span class="line">576</span><br><span class="line">577</span><br><span class="line">578</span><br><span class="line">579</span><br><span class="line">580</span><br><span class="line">581</span><br><span class="line">582</span><br><span class="line">583</span><br><span class="line">584</span><br><span class="line">585</span><br><span class="line">586</span><br><span class="line">587</span><br><span class="line">588</span><br><span class="line">589</span><br><span class="line">590</span><br><span class="line">591</span><br><span class="line">592</span><br><span class="line">593</span><br><span class="line">594</span><br><span class="line">595</span><br><span class="line">596</span><br><span class="line">597</span><br><span class="line">598</span><br><span class="line">599</span><br><span class="line">600</span><br><span class="line">601</span><br><span class="line">602</span><br><span class="line">603</span><br><span class="line">604</span><br><span class="line">605</span><br><span class="line">606</span><br><span class="line">607</span><br><span class="line">608</span><br><span class="line">609</span><br><span class="line">610</span><br><span class="line">611</span><br><span class="line">612</span><br><span class="line">613</span><br><span class="line">614</span><br><span class="line">615</span><br><span class="line">616</span><br><span class="line">617</span><br><span class="line">618</span><br><span class="line">619</span><br><span class="line">620</span><br><span class="line">621</span><br><span class="line">622</span><br><span class="line">623</span><br><span class="line">624</span><br><span class="line">625</span><br><span class="line">626</span><br><span class="line">627</span><br><span class="line">628</span><br><span class="line">629</span><br><span class="line">630</span><br><span class="line">631</span><br><span class="line">632</span><br><span class="line">633</span><br><span class="line">634</span><br><span class="line">635</span><br><span class="line">636</span><br><span class="line">637</span><br><span class="line">638</span><br><span class="line">639</span><br><span class="line">640</span><br><span class="line">641</span><br><span class="line">642</span><br><span class="line">643</span><br><span class="line">644</span><br><span class="line">645</span><br><span class="line">646</span><br><span class="line">647</span><br><span class="line">648</span><br><span class="line">649</span><br><span class="line">650</span><br><span class="line">651</span><br><span class="line">652</span><br><span class="line">653</span><br><span class="line">654</span><br><span class="line">655</span><br><span class="line">656</span><br><span class="line">657</span><br><span class="line">658</span><br><span class="line">659</span><br><span class="line">660</span><br><span class="line">661</span><br><span class="line">662</span><br><span class="line">663</span><br><span class="line">664</span><br><span class="line">665</span><br><span class="line">666</span><br><span class="line">667</span><br><span class="line">668</span><br><span class="line">669</span><br><span class="line">670</span><br><span class="line">671</span><br><span class="line">672</span><br><span class="line">673</span><br><span class="line">674</span><br><span class="line">675</span><br><span class="line">676</span><br><span class="line">677</span><br><span class="line">678</span><br><span class="line">679</span><br><span class="line">680</span><br><span class="line">681</span><br><span class="line">682</span><br><span class="line">683</span><br><span class="line">684</span><br><span class="line">685</span><br><span class="line">686</span><br><span class="line">687</span><br><span class="line">688</span><br><span class="line">689</span><br><span class="line">690</span><br><span class="line">691</span><br><span class="line">692</span><br><span class="line">693</span><br><span class="line">694</span><br><span class="line">695</span><br><span class="line">696</span><br><span class="line">697</span><br><span class="line">698</span><br><span class="line">699</span><br><span class="line">700</span><br><span class="line">701</span><br><span class="line">702</span><br><span class="line">703</span><br><span class="line">704</span><br><span class="line">705</span><br><span class="line">706</span><br><span class="line">707</span><br><span class="line">708</span><br><span class="line">709</span><br><span class="line">710</span><br><span class="line">711</span><br><span class="line">712</span><br><span class="line">713</span><br><span class="line">714</span><br><span class="line">715</span><br><span class="line">716</span><br><span class="line">717</span><br><span class="line">718</span><br><span class="line">719</span><br><span class="line">720</span><br><span class="line">721</span><br><span class="line">722</span><br><span class="line">723</span><br><span class="line">724</span><br><span class="line">725</span><br><span class="line">726</span><br><span class="line">727</span><br><span class="line">728</span><br><span class="line">729</span><br><span class="line">730</span><br><span class="line">731</span><br><span class="line">732</span><br><span class="line">733</span><br><span class="line">734</span><br><span class="line">735</span><br><span class="line">736</span><br><span class="line">737</span><br><span class="line">738</span><br><span class="line">739</span><br><span class="line">740</span><br><span class="line">741</span><br><span class="line">742</span><br><span class="line">743</span><br><span class="line">744</span><br><span class="line">745</span><br><span class="line">746</span><br><span class="line">747</span><br><span class="line">748</span><br><span class="line">749</span><br><span class="line">750</span><br><span class="line">751</span><br><span class="line">752</span><br><span class="line">753</span><br><span class="line">754</span><br><span class="line">755</span><br><span class="line">756</span><br><span class="line">757</span><br><span class="line">758</span><br><span class="line">759</span><br><span class="line">760</span><br><span class="line">761</span><br><span class="line">762</span><br><span class="line">763</span><br><span class="line">764</span><br><span class="line">765</span><br><span class="line">766</span><br><span class="line">767</span><br><span class="line">768</span><br><span class="line">769</span><br><span class="line">770</span><br><span class="line">771</span><br><span class="line">772</span><br><span class="line">773</span><br><span class="line">774</span><br><span class="line">775</span><br><span class="line">776</span><br><span class="line">777</span><br><span class="line">778</span><br><span class="line">779</span><br><span class="line">780</span><br><span class="line">781</span><br><span class="line">782</span><br><span class="line">783</span><br><span class="line">784</span><br><span class="line">785</span><br><span class="line">786</span><br><span class="line">787</span><br><span class="line">788</span><br><span class="line">789</span><br><span class="line">790</span><br><span class="line">791</span><br><span class="line">792</span><br><span class="line">793</span><br><span class="line">794</span><br><span class="line">795</span><br><span class="line">796</span><br><span class="line">797</span><br><span class="line">798</span><br><span class="line">799</span><br><span class="line">800</span><br><span class="line">801</span><br><span class="line">802</span><br><span class="line">803</span><br><span class="line">804</span><br><span class="line">805</span><br><span class="line">806</span><br><span class="line">807</span><br><span class="line">808</span><br><span class="line">809</span><br><span class="line">810</span><br><span class="line">811</span><br><span class="line">812</span><br><span class="line">813</span><br><span class="line">814</span><br><span class="line">815</span><br><span class="line">816</span><br><span class="line">817</span><br><span class="line">818</span><br><span class="line">819</span><br><span class="line">820</span><br><span class="line">821</span><br><span class="line">822</span><br><span class="line">823</span><br><span class="line">824</span><br><span class="line">825</span><br><span class="line">826</span><br><span class="line">827</span><br><span class="line">828</span><br><span class="line">829</span><br><span class="line">830</span><br><span class="line">831</span><br><span class="line">832</span><br><span class="line">833</span><br><span class="line">834</span><br><span class="line">835</span><br><span class="line">836</span><br><span class="line">837</span><br><span class="line">838</span><br><span class="line">839</span><br><span class="line">840</span><br><span class="line">841</span><br><span class="line">842</span><br><span class="line">843</span><br><span class="line">844</span><br><span class="line">845</span><br><span class="line">846</span><br><span class="line">847</span><br><span class="line">848</span><br><span class="line">849</span><br><span class="line">850</span><br><span class="line">851</span><br><span class="line">852</span><br><span class="line">853</span><br><span class="line">854</span><br><span class="line">855</span><br><span class="line">856</span><br><span class="line">857</span><br><span class="line">858</span><br><span class="line">859</span><br><span class="line">860</span><br><span class="line">861</span><br><span class="line">862</span><br><span class="line">863</span><br><span class="line">864</span><br><span class="line">865</span><br><span class="line">866</span><br><span class="line">867</span><br><span class="line">868</span><br><span class="line">869</span><br><span class="line">870</span><br><span class="line">871</span><br><span class="line">872</span><br><span class="line">873</span><br><span class="line">874</span><br><span class="line">875</span><br><span class="line">876</span><br><span class="line">877</span><br><span class="line">878</span><br><span class="line">879</span><br><span class="line">880</span><br><span class="line">881</span><br><span class="line">882</span><br><span class="line">883</span><br><span class="line">884</span><br><span class="line">885</span><br><span class="line">886</span><br><span class="line">887</span><br><span class="line">888</span><br><span class="line">889</span><br><span class="line">890</span><br><span class="line">891</span><br><span class="line">892</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">static</span> <span class="keyword">void</span></span><br><span class="line">build_lrouter_flows(struct hmap *datapaths, struct hmap *ports,</span><br><span class="line">                    struct hmap *lflows)</span><br><span class="line">&#123;</span><br><span class="line">    <span class="comment">//ingress 表0 100优先级的入口控制</span></span><br><span class="line">    <span class="class"><span class="keyword">struct</span> <span class="title">ovn_datapath</span> *<span class="title">od</span>;</span></span><br><span class="line">    HMAP_FOR_EACH (od, key_node, datapaths) &#123;</span><br><span class="line">        <span class="comment">//带VLAN标签的报文丢弃</span></span><br><span class="line">        <span class="comment">//源地址多播或者广播的报文丢弃</span></span><br><span class="line">        ovn_lflow_add(lflows, od, S_ROUTER_IN_ADMISSION, <span class="number">100</span>,</span><br><span class="line">                      <span class="string">"vlan.present || eth.src[40]"</span>, <span class="string">"drop;"</span>);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">//ingress 表0 50优先级的端口安全控制</span></span><br><span class="line">    <span class="comment">//允许端口配置的MAC和广播MAC的报文传输</span></span><br><span class="line">    <span class="class"><span class="keyword">struct</span> <span class="title">ovn_port</span> *<span class="title">op</span>;</span></span><br><span class="line">    HMAP_FOR_EACH (op, key_node, ports) &#123;</span><br><span class="line">        ds_put_format(&amp;match, <span class="string">"eth.mcast &amp;&amp; inport == %s"</span>, op-&gt;json_key);</span><br><span class="line">        ovn_lflow_add(lflows, op-&gt;od, S_ROUTER_IN_ADMISSION, <span class="number">50</span>,</span><br><span class="line">                      ds_cstr(&amp;match), <span class="string">"next;"</span>);</span><br><span class="line"></span><br><span class="line">        ds_clear(&amp;match);</span><br><span class="line">        ds_put_format(&amp;match, <span class="string">"eth.dst == %s &amp;&amp; inport == %s"</span>,</span><br><span class="line">                      op-&gt;lrp_networks.ea_s, op-&gt;json_key);</span><br><span class="line">        <span class="keyword">if</span> (op-&gt;od-&gt;l3dgw_port &amp;&amp; op == op-&gt;od-&gt;l3dgw_port</span><br><span class="line">            &amp;&amp; op-&gt;od-&gt;l3redirect_port) &#123;</span><br><span class="line">            <span class="comment">//是不是端口转发???</span></span><br><span class="line">            ds_put_format(&amp;match, <span class="string">" &amp;&amp; is_chassis_resident(%s)"</span>,</span><br><span class="line">                          op-&gt;od-&gt;l3redirect_port-&gt;json_key);</span><br><span class="line">        &#125;</span><br><span class="line">        ovn_lflow_add(lflows, op-&gt;od, S_ROUTER_IN_ADMISSION, <span class="number">50</span>,</span><br><span class="line">                      ds_cstr(&amp;match), <span class="string">"next;"</span>);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">//ingress 表1 ip input的一些固定设置</span></span><br><span class="line">    HMAP_FOR_EACH (od, key_node, datapaths) &#123;</span><br><span class="line">        <span class="comment">//优先级100，不合规的报文不准通过</span></span><br><span class="line">        ovn_lflow_add(lflows, od, S_ROUTER_IN_IP_INPUT, <span class="number">100</span>,</span><br><span class="line">                      <span class="string">"ip4.mcast || "</span></span><br><span class="line">                      <span class="string">"ip4.src == 255.255.255.255 || "</span></span><br><span class="line">                      <span class="string">"ip4.src == 127.0.0.0/8 || "</span></span><br><span class="line">                      <span class="string">"ip4.dst == 127.0.0.0/8 || "</span></span><br><span class="line">                      <span class="string">"ip4.src == 0.0.0.0/8 || "</span></span><br><span class="line">                      <span class="string">"ip4.dst == 0.0.0.0/8"</span>,</span><br><span class="line">                      <span class="string">"drop;"</span>);</span><br><span class="line"></span><br><span class="line">        <span class="comment">//90优先级，ARP reply报文，存储在逻辑交换的ARP表，即MAC_Binding</span></span><br><span class="line">        ovn_lflow_add(lflows, od, S_ROUTER_IN_IP_INPUT, <span class="number">90</span>, <span class="string">"arp.op == 2"</span>,</span><br><span class="line">                      <span class="string">"put_arp(inport, arp.spa, arp.sha);"</span>);</span><br><span class="line"></span><br><span class="line">        <span class="comment">//50优先级，逻辑路由不能发送广播包，所以丢弃</span></span><br><span class="line">        ovn_lflow_add(lflows, od, S_ROUTER_IN_IP_INPUT, <span class="number">50</span>,</span><br><span class="line">                      <span class="string">"eth.bcast"</span>, <span class="string">"drop;"</span>);</span><br><span class="line"></span><br><span class="line">        <span class="comment">//30优先级，ttl消亡的报文丢弃</span></span><br><span class="line">        ds_clear(&amp;match);</span><br><span class="line">        ds_put_cstr(&amp;match, <span class="string">"ip4 &amp;&amp; ip.ttl == &#123;0, 1&#125;"</span>);</span><br><span class="line">        ovn_lflow_add(lflows, od, S_ROUTER_IN_IP_INPUT, <span class="number">30</span>,</span><br><span class="line">                      ds_cstr(&amp;match), <span class="string">"drop;"</span>);</span><br><span class="line"></span><br><span class="line">        <span class="comment">//0优先级，放过</span></span><br><span class="line">        ovn_lflow_add(lflows, od, S_ROUTER_IN_IP_INPUT, <span class="number">0</span>, <span class="string">"1"</span>, <span class="string">"next;"</span>);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">//ingress 表1 ip input的设置，根据具体的IP情况</span></span><br><span class="line">    HMAP_FOR_EACH (op, key_node, ports) &#123;</span><br><span class="line">        <span class="keyword">if</span> (op-&gt;lrp_networks.n_ipv4_addrs) &#123;</span><br><span class="line">            <span class="comment">//100优先级，源IP是逻辑路由端口IP或者广播IP的丢掉</span></span><br><span class="line">            ds_clear(&amp;match);</span><br><span class="line">            ds_put_cstr(&amp;match, <span class="string">"ip4.src == "</span>);</span><br><span class="line">            op_put_v4_networks(&amp;match, op, <span class="literal">true</span>);</span><br><span class="line">            ds_put_cstr(&amp;match, <span class="string">" &amp;&amp; "</span>REGBIT_EGRESS_LOOPBACK<span class="string">" == 0"</span>);</span><br><span class="line">            ovn_lflow_add(lflows, op-&gt;od, S_ROUTER_IN_IP_INPUT, <span class="number">100</span>,</span><br><span class="line">                          ds_cstr(&amp;match), <span class="string">"drop;"</span>);</span><br><span class="line"></span><br><span class="line">            <span class="comment">//90优先级，对逻辑路由内IP的ICMP echo requests报文进行回复</span></span><br><span class="line">            ds_clear(&amp;match);</span><br><span class="line">            ds_put_cstr(&amp;match, <span class="string">"ip4.dst == "</span>);</span><br><span class="line">            op_put_v4_networks(&amp;match, op, <span class="literal">false</span>);</span><br><span class="line">            ds_put_cstr(&amp;match, <span class="string">" &amp;&amp; icmp4.type == 8 &amp;&amp; icmp4.code == 0"</span>);</span><br><span class="line"></span><br><span class="line">            ds_clear(&amp;actions);</span><br><span class="line">            ds_put_format(&amp;actions,</span><br><span class="line">                <span class="string">"ip4.dst &lt;-&gt; ip4.src; "</span></span><br><span class="line">                <span class="string">"ip.ttl = 255; "</span></span><br><span class="line">                <span class="string">"icmp4.type = 0; "</span></span><br><span class="line">                <span class="string">"flags.loopback = 1; "</span></span><br><span class="line">                <span class="string">"next; "</span>);</span><br><span class="line">            ovn_lflow_add(lflows, op-&gt;od, S_ROUTER_IN_IP_INPUT, <span class="number">90</span>,</span><br><span class="line">                          ds_cstr(&amp;match), ds_cstr(&amp;actions));</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="comment">//90优先级，针对逻辑路由内IP的ARP requests进行回复</span></span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; op-&gt;lrp_networks.n_ipv4_addrs; i++) &#123;</span><br><span class="line">            ds_clear(&amp;match);</span><br><span class="line">            ds_put_format(&amp;match,</span><br><span class="line">                          <span class="string">"inport == %s &amp;&amp; arp.tpa == %s &amp;&amp; arp.op == 1"</span>,</span><br><span class="line">                          op-&gt;json_key, op-&gt;lrp_networks.ipv4_addrs[i].addr_s);</span><br><span class="line">            <span class="keyword">if</span> (op-&gt;od-&gt;l3dgw_port &amp;&amp; op == op-&gt;od-&gt;l3dgw_port</span><br><span class="line">                &amp;&amp; op-&gt;od-&gt;l3redirect_port) &#123;</span><br><span class="line">                ds_put_format(&amp;match, <span class="string">" &amp;&amp; is_chassis_resident(%s)"</span>,</span><br><span class="line">                              op-&gt;od-&gt;l3redirect_port-&gt;json_key);</span><br><span class="line">            &#125;</span><br><span class="line"></span><br><span class="line">            ds_clear(&amp;actions);</span><br><span class="line">            ds_put_format(&amp;actions,</span><br><span class="line">                <span class="string">"eth.dst = eth.src; "</span></span><br><span class="line">                <span class="string">"eth.src = %s; "</span></span><br><span class="line">                <span class="string">"arp.op = 2; /* ARP reply */ "</span></span><br><span class="line">                <span class="string">"arp.tha = arp.sha; "</span></span><br><span class="line">                <span class="string">"arp.sha = %s; "</span></span><br><span class="line">                <span class="string">"arp.tpa = arp.spa; "</span></span><br><span class="line">                <span class="string">"arp.spa = %s; "</span></span><br><span class="line">                <span class="string">"outport = %s; "</span></span><br><span class="line">                <span class="string">"flags.loopback = 1; "</span></span><br><span class="line">                <span class="string">"output;"</span>,</span><br><span class="line">                op-&gt;lrp_networks.ea_s,</span><br><span class="line">                op-&gt;lrp_networks.ea_s,</span><br><span class="line">                op-&gt;lrp_networks.ipv4_addrs[i].addr_s,</span><br><span class="line">                op-&gt;json_key);</span><br><span class="line">            ovn_lflow_add(lflows, op-&gt;od, S_ROUTER_IN_IP_INPUT, <span class="number">90</span>,</span><br><span class="line">                          ds_cstr(&amp;match), ds_cstr(&amp;actions));</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="comment">//LB的VIP也需要ARP responses的报文进行回复，同上的操作</span></span><br><span class="line">        <span class="class"><span class="keyword">struct</span> <span class="title">sset</span> <span class="title">all_ips</span> = <span class="title">SSET_INITIALIZER</span>(&amp;<span class="title">all_ips</span>);</span></span><br><span class="line"></span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; op-&gt;od-&gt;nbr-&gt;n_load_balancer; i++) &#123;</span><br><span class="line">            <span class="class"><span class="keyword">struct</span> <span class="title">nbrec_load_balancer</span> *<span class="title">lb</span> = <span class="title">op</span>-&gt;<span class="title">od</span>-&gt;<span class="title">nbr</span>-&gt;<span class="title">load_balancer</span>[<span class="title">i</span>];</span></span><br><span class="line">            <span class="class"><span class="keyword">struct</span> <span class="title">smap</span> *<span class="title">vips</span> = &amp;<span class="title">lb</span>-&gt;<span class="title">vips</span>;</span></span><br><span class="line">            <span class="class"><span class="keyword">struct</span> <span class="title">smap_node</span> *<span class="title">node</span>;</span></span><br><span class="line"></span><br><span class="line">            SMAP_FOR_EACH (node, vips) &#123;</span><br><span class="line">                <span class="keyword">char</span> *ip_address = <span class="literal">NULL</span>;</span><br><span class="line">                <span class="keyword">uint16_t</span> port;</span><br><span class="line"></span><br><span class="line">                ip_address_and_port_from_lb_key(node-&gt;key, &amp;ip_address, &amp;port);</span><br><span class="line">                <span class="keyword">if</span> (!sset_contains(&amp;all_ips, ip_address)) &#123;</span><br><span class="line">                    sset_add(&amp;all_ips, ip_address);</span><br><span class="line">                &#125;</span><br><span class="line"></span><br><span class="line">                <span class="built_in">free</span>(ip_address);</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">const</span> <span class="keyword">char</span> *ip_address;</span><br><span class="line">        SSET_FOR_EACH(ip_address, &amp;all_ips) &#123;</span><br><span class="line">            ds_clear(&amp;match);</span><br><span class="line">            ds_put_format(&amp;match,</span><br><span class="line">                          <span class="string">"inport == %s &amp;&amp; arp.tpa == "</span>IP_FMT<span class="string">" &amp;&amp; arp.op == 1"</span>,</span><br><span class="line">                          op-&gt;json_key, IP_ARGS(ip));</span><br><span class="line"></span><br><span class="line">            ds_clear(&amp;actions);</span><br><span class="line">            ds_put_format(&amp;actions,</span><br><span class="line">                <span class="string">"eth.dst = eth.src; "</span></span><br><span class="line">                <span class="string">"eth.src = %s; "</span></span><br><span class="line">                <span class="string">"arp.op = 2; /* ARP reply */ "</span></span><br><span class="line">                <span class="string">"arp.tha = arp.sha; "</span></span><br><span class="line">                <span class="string">"arp.sha = %s; "</span></span><br><span class="line">                <span class="string">"arp.tpa = arp.spa; "</span></span><br><span class="line">                <span class="string">"arp.spa = "</span>IP_FMT<span class="string">"; "</span></span><br><span class="line">                <span class="string">"outport = %s; "</span></span><br><span class="line">                <span class="string">"flags.loopback = 1; "</span></span><br><span class="line">                <span class="string">"output;"</span>,</span><br><span class="line">                op-&gt;lrp_networks.ea_s,</span><br><span class="line">                op-&gt;lrp_networks.ea_s,</span><br><span class="line">                IP_ARGS(ip),</span><br><span class="line">                op-&gt;json_key);</span><br><span class="line">            ovn_lflow_add(lflows, op-&gt;od, S_ROUTER_IN_IP_INPUT, <span class="number">90</span>,</span><br><span class="line">                          ds_cstr(&amp;match), ds_cstr(&amp;actions));</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">        <span class="comment">/* A gateway router can have 2 SNAT IP addresses to force DNATed and</span></span><br><span class="line"><span class="comment">         * LBed traffic respectively to be SNATed.  In addition, there can be</span></span><br><span class="line"><span class="comment">         * a number of SNAT rules in the NAT table. */</span></span><br><span class="line">        ovs_be32 *snat_ips = xmalloc(<span class="keyword">sizeof</span> *snat_ips *</span><br><span class="line">                                     (op-&gt;od-&gt;nbr-&gt;n_nat + <span class="number">2</span>));</span><br><span class="line">        <span class="keyword">size_t</span> n_snat_ips = <span class="number">0</span>;</span><br><span class="line"></span><br><span class="line">        ovs_be32 snat_ip;</span><br><span class="line">        <span class="keyword">const</span> <span class="keyword">char</span> *dnat_force_snat_ip = get_force_snat_ip(op-&gt;od, <span class="string">"dnat"</span>,</span><br><span class="line">                                                           &amp;snat_ip);</span><br><span class="line">        <span class="keyword">if</span> (dnat_force_snat_ip) &#123;</span><br><span class="line">            snat_ips[n_snat_ips++] = snat_ip;</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">const</span> <span class="keyword">char</span> *lb_force_snat_ip = get_force_snat_ip(op-&gt;od, <span class="string">"lb"</span>,</span><br><span class="line">                                                         &amp;snat_ip);</span><br><span class="line">        <span class="keyword">if</span> (lb_force_snat_ip) &#123;</span><br><span class="line">            snat_ips[n_snat_ips++] = snat_ip;</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; op-&gt;od-&gt;nbr-&gt;n_nat; i++) &#123;</span><br><span class="line">            <span class="keyword">const</span> <span class="class"><span class="keyword">struct</span> <span class="title">nbrec_nat</span> *<span class="title">nat</span>;</span></span><br><span class="line"></span><br><span class="line">            nat = op-&gt;od-&gt;nbr-&gt;nat[i];</span><br><span class="line"></span><br><span class="line">            ovs_be32 ip;</span><br><span class="line">            <span class="keyword">if</span> (!ip_parse(nat-&gt;external_ip, &amp;ip) || !ip) &#123;</span><br><span class="line">                <span class="keyword">static</span> <span class="class"><span class="keyword">struct</span> <span class="title">vlog_rate_limit</span> <span class="title">rl</span> = <span class="title">VLOG_RATE_LIMIT_INIT</span>(5, 1);</span></span><br><span class="line">                VLOG_WARN_RL(&amp;rl, <span class="string">"bad ip address %s in nat configuration "</span></span><br><span class="line">                             <span class="string">"for router %s"</span>, nat-&gt;external_ip, op-&gt;key);</span><br><span class="line">                <span class="keyword">continue</span>;</span><br><span class="line">            &#125;</span><br><span class="line"></span><br><span class="line">            <span class="keyword">if</span> (!<span class="built_in">strcmp</span>(nat-&gt;type, <span class="string">"snat"</span>)) &#123;</span><br><span class="line">                snat_ips[n_snat_ips++] = ip;</span><br><span class="line">                <span class="keyword">continue</span>;</span><br><span class="line">            &#125;</span><br><span class="line"></span><br><span class="line">            <span class="comment">//EIP(DNAT)需要的arp处理</span></span><br><span class="line">            ds_clear(&amp;match);</span><br><span class="line">            ds_put_format(&amp;match,</span><br><span class="line">                          <span class="string">"inport == %s &amp;&amp; arp.tpa == "</span>IP_FMT<span class="string">" &amp;&amp; arp.op == 1"</span>,</span><br><span class="line">                          op-&gt;json_key, IP_ARGS(ip));</span><br><span class="line"></span><br><span class="line">            ds_clear(&amp;actions);</span><br><span class="line">            ds_put_format(&amp;actions,</span><br><span class="line">                <span class="string">"eth.dst = eth.src; "</span></span><br><span class="line">                <span class="string">"arp.op = 2; /* ARP reply */ "</span></span><br><span class="line">                <span class="string">"arp.tha = arp.sha; "</span>);</span><br><span class="line"></span><br><span class="line">            <span class="comment">//说实话，这块没懂</span></span><br><span class="line">            <span class="keyword">if</span> (op-&gt;od-&gt;l3dgw_port &amp;&amp; op == op-&gt;od-&gt;l3dgw_port) &#123;</span><br><span class="line">                <span class="class"><span class="keyword">struct</span> <span class="title">eth_addr</span> <span class="title">mac</span>;</span></span><br><span class="line">                <span class="keyword">if</span> (nat-&gt;external_mac &amp;&amp;</span><br><span class="line">                    eth_addr_from_string(nat-&gt;external_mac, &amp;mac)</span><br><span class="line">                    &amp;&amp; nat-&gt;logical_port) &#123;</span><br><span class="line">                    <span class="comment">//分布式NAT的场景，回复的源MAC是nat-&gt;external_mac</span></span><br><span class="line">                    ds_put_format(&amp;actions,</span><br><span class="line">                        <span class="string">"eth.src = "</span>ETH_ADDR_FMT<span class="string">"; "</span></span><br><span class="line">                        <span class="string">"arp.sha = "</span>ETH_ADDR_FMT<span class="string">"; "</span>,</span><br><span class="line">                        ETH_ADDR_ARGS(mac),</span><br><span class="line">                        ETH_ADDR_ARGS(mac));</span><br><span class="line">                    ds_put_format(&amp;match, <span class="string">" &amp;&amp; is_chassis_resident(\"%s\")"</span>,</span><br><span class="line">                                  nat-&gt;logical_port);</span><br><span class="line">                &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                    <span class="comment">//网络节点的NAT场景，回复的源MAC是网关的MAC</span></span><br><span class="line">                    ds_put_format(&amp;actions,</span><br><span class="line">                        <span class="string">"eth.src = %s; "</span></span><br><span class="line">                        <span class="string">"arp.sha = %s; "</span>,</span><br><span class="line">                        op-&gt;lrp_networks.ea_s,</span><br><span class="line">                        op-&gt;lrp_networks.ea_s);</span><br><span class="line">                    <span class="keyword">if</span> (op-&gt;od-&gt;l3redirect_port) &#123;</span><br><span class="line">                        ds_put_format(&amp;match, <span class="string">" &amp;&amp; is_chassis_resident(%s)"</span>,</span><br><span class="line">                                      op-&gt;od-&gt;l3redirect_port-&gt;json_key);</span><br><span class="line">                    &#125;</span><br><span class="line">                &#125;</span><br><span class="line">            &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                ds_put_format(&amp;actions,</span><br><span class="line">                    <span class="string">"eth.src = %s; "</span></span><br><span class="line">                    <span class="string">"arp.sha = %s; "</span>,</span><br><span class="line">                    op-&gt;lrp_networks.ea_s,</span><br><span class="line">                    op-&gt;lrp_networks.ea_s);</span><br><span class="line">            &#125;</span><br><span class="line">            ds_put_format(&amp;actions,</span><br><span class="line">                <span class="string">"arp.tpa = arp.spa; "</span></span><br><span class="line">                <span class="string">"arp.spa = "</span>IP_FMT<span class="string">"; "</span></span><br><span class="line">                <span class="string">"outport = %s; "</span></span><br><span class="line">                <span class="string">"flags.loopback = 1; "</span></span><br><span class="line">                <span class="string">"output;"</span>,</span><br><span class="line">                IP_ARGS(ip),</span><br><span class="line">                op-&gt;json_key);</span><br><span class="line">            ovn_lflow_add(lflows, op-&gt;od, S_ROUTER_IN_IP_INPUT, <span class="number">90</span>,</span><br><span class="line">                          ds_cstr(&amp;match), ds_cstr(&amp;actions));</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        ds_clear(&amp;match);</span><br><span class="line">        ds_put_cstr(&amp;match, <span class="string">"ip4.dst == &#123;"</span>);</span><br><span class="line">        <span class="keyword">bool</span> has_drop_ips = <span class="literal">false</span>;</span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; op-&gt;lrp_networks.n_ipv4_addrs; i++) &#123;</span><br><span class="line">            <span class="keyword">bool</span> snat_ip_is_router_ip = <span class="literal">false</span>;</span><br><span class="line">            <span class="keyword">for</span> (<span class="keyword">int</span> j = <span class="number">0</span>; j &lt; n_snat_ips; j++) &#123;</span><br><span class="line">                <span class="comment">//到SNAT IP的报文丢弃，因为这是一个虚拟IP，不处理任何报文</span></span><br><span class="line">                <span class="keyword">if</span> (op-&gt;lrp_networks.ipv4_addrs[i].addr == snat_ips[j]) &#123;</span><br><span class="line">                    snat_ip_is_router_ip = <span class="literal">true</span>;</span><br><span class="line">                    <span class="keyword">break</span>;</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="keyword">if</span> (snat_ip_is_router_ip) &#123;</span><br><span class="line">                <span class="keyword">continue</span>;</span><br><span class="line">            &#125;</span><br><span class="line">            ds_put_format(&amp;match, <span class="string">"%s, "</span>,</span><br><span class="line">                          op-&gt;lrp_networks.ipv4_addrs[i].addr_s);</span><br><span class="line">            has_drop_ips = <span class="literal">true</span>;</span><br><span class="line">        &#125;</span><br><span class="line">        ds_chomp(&amp;match, <span class="string">' '</span>);</span><br><span class="line">        ds_chomp(&amp;match, <span class="string">','</span>);</span><br><span class="line">        ds_put_cstr(&amp;match, <span class="string">"&#125;"</span>);</span><br><span class="line"></span><br><span class="line">        <span class="keyword">if</span> (has_drop_ips) &#123;</span><br><span class="line">            <span class="comment">//到网关router的报文也不处理，之前的ARP和ICMP已经代答</span></span><br><span class="line">            ovn_lflow_add(lflows, op-&gt;od, S_ROUTER_IN_IP_INPUT, <span class="number">60</span>,</span><br><span class="line">                          ds_cstr(&amp;match), <span class="string">"drop;"</span>);</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="built_in">free</span>(snat_ips);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">//处理NAT、分片和LB的操作</span></span><br><span class="line">    HMAP_FOR_EACH (od, key_node, datapaths) &#123;</span><br><span class="line">        <span class="comment">//ingress的表2-4，egress的表0-3的默认流表0优先级是通过</span></span><br><span class="line">        ovn_lflow_add(lflows, od, S_ROUTER_IN_DEFRAG, <span class="number">0</span>, <span class="string">"1"</span>, <span class="string">"next;"</span>);</span><br><span class="line">        ovn_lflow_add(lflows, od, S_ROUTER_IN_UNSNAT, <span class="number">0</span>, <span class="string">"1"</span>, <span class="string">"next;"</span>);</span><br><span class="line">        ovn_lflow_add(lflows, od, S_ROUTER_OUT_SNAT, <span class="number">0</span>, <span class="string">"1"</span>, <span class="string">"next;"</span>);</span><br><span class="line">        ovn_lflow_add(lflows, od, S_ROUTER_IN_DNAT, <span class="number">0</span>, <span class="string">"1"</span>, <span class="string">"next;"</span>);</span><br><span class="line">        ovn_lflow_add(lflows, od, S_ROUTER_OUT_UNDNAT, <span class="number">0</span>, <span class="string">"1"</span>, <span class="string">"next;"</span>);</span><br><span class="line">        ovn_lflow_add(lflows, od, S_ROUTER_OUT_EGR_LOOP, <span class="number">0</span>, <span class="string">"1"</span>, <span class="string">"next;"</span>);</span><br><span class="line"></span><br><span class="line">        <span class="keyword">if</span> (!smap_get(&amp;od-&gt;nbr-&gt;options, <span class="string">"chassis"</span>) &amp;&amp; !od-&gt;l3dgw_port</span><br><span class="line">            &amp;&amp; !smap_get(&amp;od-&gt;nbr-&gt;options, <span class="string">"underlay-gateway"</span>)) &#123;</span><br><span class="line">            <span class="keyword">continue</span>;</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        ovs_be32 snat_ip;</span><br><span class="line">        <span class="keyword">const</span> <span class="keyword">char</span> *dnat_force_snat_ip = get_force_snat_ip(od, <span class="string">"dnat"</span>,</span><br><span class="line">                                                           &amp;snat_ip);</span><br><span class="line">        <span class="keyword">const</span> <span class="keyword">char</span> *lb_force_snat_ip = get_force_snat_ip(od, <span class="string">"lb"</span>,</span><br><span class="line">                                                         &amp;snat_ip);</span><br><span class="line"></span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; od-&gt;nbr-&gt;n_nat; i++) &#123;</span><br><span class="line">            <span class="keyword">const</span> <span class="class"><span class="keyword">struct</span> <span class="title">nbrec_nat</span> *<span class="title">nat</span>;</span></span><br><span class="line"></span><br><span class="line">            nat = od-&gt;nbr-&gt;nat[i];</span><br><span class="line"></span><br><span class="line">            ovs_be32 ip, mask;</span><br><span class="line"></span><br><span class="line">            <span class="keyword">char</span> *error = ip_parse_masked(nat-&gt;external_ip, &amp;ip, &amp;mask);</span><br><span class="line">            <span class="keyword">if</span> (error || mask != OVS_BE32_MAX) &#123;</span><br><span class="line">                <span class="keyword">static</span> <span class="class"><span class="keyword">struct</span> <span class="title">vlog_rate_limit</span> <span class="title">rl</span> = <span class="title">VLOG_RATE_LIMIT_INIT</span>(5, 1);</span></span><br><span class="line">                VLOG_WARN_RL(&amp;rl, <span class="string">"bad external ip %s for nat"</span>,</span><br><span class="line">                             nat-&gt;external_ip);</span><br><span class="line">                <span class="built_in">free</span>(error);</span><br><span class="line">                <span class="keyword">continue</span>;</span><br><span class="line">            &#125;</span><br><span class="line"></span><br><span class="line">            <span class="comment">//检测NAT的logical_ip是否合理，SNAT的时候，logical_ip可以是一个子网</span></span><br><span class="line">            error = ip_parse_masked(nat-&gt;logical_ip, &amp;ip, &amp;mask);</span><br><span class="line">            <span class="keyword">if</span> (!<span class="built_in">strcmp</span>(nat-&gt;type, <span class="string">"snat"</span>)) &#123;</span><br><span class="line">                <span class="keyword">if</span> (error) &#123;</span><br><span class="line">                    <span class="keyword">static</span> <span class="class"><span class="keyword">struct</span> <span class="title">vlog_rate_limit</span> <span class="title">rl</span> =</span></span><br><span class="line"><span class="class">                        <span class="title">VLOG_RATE_LIMIT_INIT</span>(5, 1);</span></span><br><span class="line">                    VLOG_WARN_RL(&amp;rl, <span class="string">"bad ip network or ip %s for snat "</span></span><br><span class="line">                                 <span class="string">"in router "</span>UUID_FMT<span class="string">""</span>,</span><br><span class="line">                                 nat-&gt;logical_ip, UUID_ARGS(&amp;od-&gt;key));</span><br><span class="line">                    <span class="built_in">free</span>(error);</span><br><span class="line">                    <span class="keyword">continue</span>;</span><br><span class="line">                &#125;</span><br><span class="line">            &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                <span class="keyword">if</span> (error || mask != OVS_BE32_MAX) &#123;</span><br><span class="line">                    <span class="keyword">static</span> struct vlog_rate_limit rl =</span><br><span class="line">                        VLOG_RATE_LIMIT_INIT(<span class="number">5</span>, <span class="number">1</span>);</span><br><span class="line">                    VLOG_WARN_RL(&amp;rl, <span class="string">"bad ip %s for dnat in router "</span></span><br><span class="line">                        <span class="string">""</span>UUID_FMT<span class="string">""</span>, nat-&gt;logical_ip, UUID_ARGS(&amp;od-&gt;key));</span><br><span class="line">                    <span class="built_in">free</span>(error);</span><br><span class="line">                    <span class="keyword">continue</span>;</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line"></span><br><span class="line">            <span class="comment">//分布式路由NAT，确定NAT规则是否满足分布式NAT的操作</span></span><br><span class="line">            <span class="keyword">bool</span> distributed = <span class="literal">false</span>;</span><br><span class="line">            <span class="class"><span class="keyword">struct</span> <span class="title">eth_addr</span> <span class="title">mac</span>;</span></span><br><span class="line">            <span class="keyword">if</span> (od-&gt;l3dgw_port &amp;&amp; !<span class="built_in">strcmp</span>(nat-&gt;type, <span class="string">"dnat_and_snat"</span>) &amp;&amp;</span><br><span class="line">                nat-&gt;logical_port &amp;&amp; nat-&gt;external_mac) &#123;</span><br><span class="line">                <span class="keyword">if</span> (eth_addr_from_string(nat-&gt;external_mac, &amp;mac)) &#123;</span><br><span class="line">                    distributed = <span class="literal">true</span>;</span><br><span class="line">                &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                    <span class="keyword">static</span> struct vlog_rate_limit rl =</span><br><span class="line">                        VLOG_RATE_LIMIT_INIT(<span class="number">5</span>, <span class="number">1</span>);</span><br><span class="line">                    VLOG_WARN_RL(&amp;rl, <span class="string">"bad mac %s for dnat in router "</span></span><br><span class="line">                        <span class="string">""</span>UUID_FMT<span class="string">""</span>, nat-&gt;external_mac, UUID_ARGS(&amp;od-&gt;key));</span><br><span class="line">                    <span class="keyword">continue</span>;</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line"></span><br><span class="line">            <span class="comment">//ingress 表3 ，必须是egress的SNAT已经创建了连接以及反向连接。</span></span><br><span class="line">            <span class="keyword">if</span> (!<span class="built_in">strcmp</span>(nat-&gt;type, <span class="string">"snat"</span>)</span><br><span class="line">                || !<span class="built_in">strcmp</span>(nat-&gt;type, <span class="string">"dnat_and_snat"</span>)) &#123;</span><br><span class="line">                <span class="keyword">if</span> (!od-&gt;l3dgw_port) &#123;</span><br><span class="line">                    <span class="comment">//网关路由</span></span><br><span class="line">                    ds_clear(&amp;match);</span><br><span class="line">                    ds_put_format(&amp;match, <span class="string">"ip &amp;&amp; ip4.dst == %s"</span>,</span><br><span class="line">                                  nat-&gt;external_ip);</span><br><span class="line">                    ovn_lflow_add(lflows, od, S_ROUTER_IN_UNSNAT, <span class="number">90</span>,</span><br><span class="line">                                  ds_cstr(&amp;match), <span class="string">"ct_snat; next;"</span>);</span><br><span class="line">                &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                    <span class="comment">//分布式路由，网关进来的报文进行unnat</span></span><br><span class="line">                    ds_clear(&amp;match);</span><br><span class="line">                    ds_put_format(&amp;match, <span class="string">"ip &amp;&amp; ip4.dst == %s"</span></span><br><span class="line">                                          <span class="string">" &amp;&amp; inport == %s"</span>,</span><br><span class="line">                                  nat-&gt;external_ip,</span><br><span class="line">                                  od-&gt;l3dgw_port-&gt;json_key);</span><br><span class="line">                    <span class="keyword">if</span> (!distributed &amp;&amp; od-&gt;l3redirect_port) &#123;</span><br><span class="line">                        ds_put_format(&amp;match, <span class="string">" &amp;&amp; is_chassis_resident(%s)"</span>,</span><br><span class="line">                                      od-&gt;l3redirect_port-&gt;json_key);</span><br><span class="line">                    &#125;</span><br><span class="line">                    ovn_lflow_add(lflows, od, S_ROUTER_IN_UNSNAT, <span class="number">100</span>,</span><br><span class="line">                                  ds_cstr(&amp;match), <span class="string">"ct_snat;"</span>);</span><br><span class="line"></span><br><span class="line">                    <span class="comment">//貌似是没有匹配上面的流表，表示不是网关端口来的</span></span><br><span class="line">                    <span class="comment">//是从其他路由端口来的，需要重定向到l3dgw_port操作NAT</span></span><br><span class="line">                    ds_clear(&amp;match);</span><br><span class="line">                    ds_put_format(&amp;match, <span class="string">"ip &amp;&amp; ip4.dst == %s"</span>,</span><br><span class="line">                                  nat-&gt;external_ip);</span><br><span class="line">                    ovn_lflow_add(lflows, od, S_ROUTER_IN_UNSNAT, <span class="number">50</span>,</span><br><span class="line">                                  ds_cstr(&amp;match),</span><br><span class="line">                                  REGBIT_NAT_REDIRECT<span class="string">" = 1; next;"</span>);</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line"></span><br><span class="line">            <span class="comment">//ingress 表4 DNAT</span></span><br><span class="line">            <span class="keyword">int</span> dnat = <span class="number">0</span>, pro = <span class="number">100</span>;</span><br><span class="line">            <span class="keyword">if</span> (!<span class="built_in">strcmp</span>(nat-&gt;type, <span class="string">"dnat"</span>)</span><br><span class="line">                || !<span class="built_in">strcmp</span>(nat-&gt;type, <span class="string">"dnat_and_snat"</span>)) &#123;</span><br><span class="line">                <span class="keyword">if</span> (!od-&gt;l3dgw_port) &#123;</span><br><span class="line">                    <span class="comment">//网关路由</span></span><br><span class="line">                    ds_clear(&amp;match);</span><br><span class="line">                    ds_put_format(&amp;match, <span class="string">"ip &amp;&amp; ip4.dst == %s"</span>,</span><br><span class="line">                                  nat-&gt;external_ip);</span><br><span class="line">                    <span class="keyword">if</span>(!<span class="built_in">strcmp</span>(nat-&gt;type, <span class="string">"dnat"</span>))&#123;</span><br><span class="line">                        <span class="keyword">if</span>(nat-&gt;eport &amp;&amp; nat-&gt;protocol)&#123;</span><br><span class="line">                            <span class="keyword">if</span>(!<span class="built_in">strcmp</span>(nat-&gt;protocol, <span class="string">"tcp"</span>)) &#123;</span><br><span class="line">                                ds_put_format(&amp;match, <span class="string">" &amp;&amp; tcp &amp;&amp; tcp.dst == %d"</span>, (<span class="keyword">uint16_t</span>)nat-&gt;eport);</span><br><span class="line">                                dnat = <span class="number">1</span>;</span><br><span class="line">                            &#125; <span class="keyword">else</span> <span class="keyword">if</span> (!<span class="built_in">strcmp</span>(nat-&gt;protocol, <span class="string">"udp"</span>)) &#123;</span><br><span class="line">                                ds_put_format(&amp;match, <span class="string">" &amp;&amp; udp &amp;&amp; udp.dst == %d"</span>, (<span class="keyword">uint16_t</span>)nat-&gt;eport);</span><br><span class="line">                                dnat = <span class="number">1</span>;</span><br><span class="line">                            &#125; <span class="keyword">else</span> &#123; <span class="keyword">continue</span>; &#125;</span><br><span class="line">                        &#125; <span class="keyword">else</span> &#123; ;&#125;</span><br><span class="line">                    &#125;</span><br><span class="line">                    ds_clear(&amp;actions);</span><br><span class="line">                    <span class="keyword">if</span> (dnat_force_snat_ip) &#123;</span><br><span class="line">                        <span class="comment">//该标志表示egress的SNAT需要执行</span></span><br><span class="line">                        ds_put_format(&amp;actions,</span><br><span class="line">                                      <span class="string">"flags.force_snat_for_dnat = 1; "</span>);</span><br><span class="line">                    &#125;</span><br><span class="line">                    <span class="keyword">if</span>(dnat) &#123;</span><br><span class="line">                        pro = <span class="number">90</span>;</span><br><span class="line">                        ds_put_format(&amp;actions, <span class="string">"flags.loopback = 1; ct_dnat(%s:%d);"</span>, nat-&gt;logical_ip, (<span class="keyword">int</span>)(nat-&gt;lport?:nat-&gt;eport));</span><br><span class="line">                    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                        ds_put_format(&amp;actions, <span class="string">"flags.loopback = 1; ct_dnat(%s);"</span>, nat-&gt;logical_ip);</span><br><span class="line">                    &#125;</span><br><span class="line">                    ovn_lflow_add(lflows, od, S_ROUTER_IN_DNAT, pro,</span><br><span class="line">                                  ds_cstr(&amp;match), ds_cstr(&amp;actions));</span><br><span class="line">                &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                    <span class="comment">//分布式路由，入端口是l3dgw_port</span></span><br><span class="line">                    ds_clear(&amp;match);</span><br><span class="line">                    ds_put_format(&amp;match, <span class="string">"ip &amp;&amp; ip4.dst == %s"</span></span><br><span class="line">                                  <span class="string">" &amp;&amp; inport == %s"</span>,</span><br><span class="line">                                  nat-&gt;external_ip,</span><br><span class="line">                                  od-&gt;l3dgw_port-&gt;json_key);</span><br><span class="line">                    <span class="keyword">if</span> (!distributed &amp;&amp; od-&gt;l3redirect_port) &#123;</span><br><span class="line">                        ds_put_format(&amp;match, <span class="string">" &amp;&amp; is_chassis_resident(%s)"</span>,</span><br><span class="line">                                      od-&gt;l3redirect_port-&gt;json_key);</span><br><span class="line">                    &#125;</span><br><span class="line">                    ds_clear(&amp;actions);</span><br><span class="line">                    ds_put_format(&amp;actions, <span class="string">"ct_dnat(%s);"</span>,</span><br><span class="line">                                  nat-&gt;logical_ip);</span><br><span class="line">                    ovn_lflow_add(lflows, od, S_ROUTER_IN_DNAT, <span class="number">100</span>,</span><br><span class="line">                                  ds_cstr(&amp;match), ds_cstr(&amp;actions));</span><br><span class="line"></span><br><span class="line">                    ds_clear(&amp;match);</span><br><span class="line">                    ds_put_format(&amp;match, <span class="string">"ip &amp;&amp; ip4.dst == %s"</span>,</span><br><span class="line">                                  nat-&gt;external_ip);</span><br><span class="line">                    ovn_lflow_add(lflows, od, S_ROUTER_IN_DNAT, <span class="number">50</span>,</span><br><span class="line">                                  ds_cstr(&amp;match),</span><br><span class="line">                                  REGBIT_NAT_REDIRECT<span class="string">" = 1; next;"</span>);</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line"></span><br><span class="line">            <span class="comment">//egress 表0 UNDNAT，必须是ingress的DNAT连接已经创建的情况下</span></span><br><span class="line">            <span class="keyword">if</span> (od-&gt;l3dgw_port &amp;&amp; (!<span class="built_in">strcmp</span>(nat-&gt;type, <span class="string">"dnat"</span>)</span><br><span class="line">                || !<span class="built_in">strcmp</span>(nat-&gt;type, <span class="string">"dnat_and_snat"</span>))) &#123;</span><br><span class="line">                ds_clear(&amp;match);</span><br><span class="line">                ds_put_format(&amp;match, <span class="string">"ip &amp;&amp; ip4.src == %s"</span></span><br><span class="line">                                      <span class="string">" &amp;&amp; outport == %s"</span>,</span><br><span class="line">                              nat-&gt;logical_ip,</span><br><span class="line">                              od-&gt;l3dgw_port-&gt;json_key);</span><br><span class="line">                <span class="keyword">if</span> (!distributed &amp;&amp; od-&gt;l3redirect_port) &#123;</span><br><span class="line">                    ds_put_format(&amp;match, <span class="string">" &amp;&amp; is_chassis_resident(%s)"</span>,</span><br><span class="line">                                  od-&gt;l3redirect_port-&gt;json_key);</span><br><span class="line">                &#125;</span><br><span class="line">                ds_clear(&amp;actions);</span><br><span class="line">                <span class="keyword">if</span> (distributed) &#123;</span><br><span class="line">                    ds_put_format(&amp;actions, <span class="string">"eth.src = "</span>ETH_ADDR_FMT<span class="string">"; "</span>,</span><br><span class="line">                                  ETH_ADDR_ARGS(mac));</span><br><span class="line">                &#125;</span><br><span class="line">                ds_put_format(&amp;actions, <span class="string">"ct_dnat;"</span>);</span><br><span class="line">                ovn_lflow_add(lflows, od, S_ROUTER_OUT_UNDNAT, <span class="number">100</span>,</span><br><span class="line">                              ds_cstr(&amp;match), ds_cstr(&amp;actions));</span><br><span class="line">            &#125;</span><br><span class="line"></span><br><span class="line">            <span class="comment">//egress 表1 SNAT</span></span><br><span class="line">            <span class="keyword">if</span> (!<span class="built_in">strcmp</span>(nat-&gt;type, <span class="string">"snat"</span>)</span><br><span class="line">                || !<span class="built_in">strcmp</span>(nat-&gt;type, <span class="string">"dnat_and_snat"</span>)) &#123;</span><br><span class="line">                <span class="keyword">if</span> (!od-&gt;l3dgw_port) &#123;</span><br><span class="line">                    <span class="comment">//网关路由</span></span><br><span class="line">                    ds_clear(&amp;match);</span><br><span class="line">                    ds_put_format(&amp;match, <span class="string">"ip &amp;&amp; ip4.src == %s"</span>,</span><br><span class="line">                                  nat-&gt;logical_ip);</span><br><span class="line">                    ds_clear(&amp;actions);</span><br><span class="line">                    ds_put_format(&amp;actions, <span class="string">"ct_snat(%s);"</span>, nat-&gt;external_ip);</span><br><span class="line"></span><br><span class="line">                    <span class="comment">//掩码越长，优先级越高</span></span><br><span class="line">                    ovn_lflow_add(lflows, od, S_ROUTER_OUT_SNAT,</span><br><span class="line">                                  count_1bits(ntohl(mask)) + <span class="number">1</span>,</span><br><span class="line">                                  ds_cstr(&amp;match), ds_cstr(&amp;actions));</span><br><span class="line">                &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                    <span class="comment">//分布式路由</span></span><br><span class="line">                    ds_clear(&amp;match);</span><br><span class="line">                    ds_put_format(&amp;match, <span class="string">"ip &amp;&amp; ip4.src == %s"</span></span><br><span class="line">                                          <span class="string">" &amp;&amp; outport == %s"</span>,</span><br><span class="line">                                  nat-&gt;logical_ip,</span><br><span class="line">                                  od-&gt;l3dgw_port-&gt;json_key);</span><br><span class="line">                    <span class="keyword">if</span> (!distributed &amp;&amp; od-&gt;l3redirect_port) &#123;</span><br><span class="line">                        ds_put_format(&amp;match, <span class="string">" &amp;&amp; is_chassis_resident(%s)"</span>,</span><br><span class="line">                                      od-&gt;l3redirect_port-&gt;json_key);</span><br><span class="line">                    &#125;</span><br><span class="line">                    ds_clear(&amp;actions);</span><br><span class="line">                    <span class="keyword">if</span> (distributed) &#123;</span><br><span class="line">                        ds_put_format(&amp;actions, <span class="string">"eth.src = "</span>ETH_ADDR_FMT<span class="string">"; "</span>,</span><br><span class="line">                                      ETH_ADDR_ARGS(mac));</span><br><span class="line">                    &#125;</span><br><span class="line">                    ds_put_format(&amp;actions, <span class="string">"ct_snat(%s);"</span>, nat-&gt;external_ip);</span><br><span class="line"></span><br><span class="line">                    <span class="comment">//同样是掩码越长，优先级越高</span></span><br><span class="line">                    ovn_lflow_add(lflows, od, S_ROUTER_OUT_SNAT,</span><br><span class="line">                                  count_1bits(ntohl(mask)) + <span class="number">1</span>,</span><br><span class="line">                                  ds_cstr(&amp;match), ds_cstr(&amp;actions));</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line"></span><br><span class="line">            <span class="comment">//ingress 表0，50优先级允许支持NAT的报文通过</span></span><br><span class="line">            <span class="comment">//入口是l3dgw_port，并且目的MAC是nat-&gt;external_mac的时候通过</span></span><br><span class="line">            <span class="keyword">if</span> (distributed) &#123;</span><br><span class="line">                ds_clear(&amp;match);</span><br><span class="line">                ds_put_format(&amp;match,</span><br><span class="line">                              <span class="string">"eth.dst == "</span>ETH_ADDR_FMT<span class="string">" &amp;&amp; inport == %s"</span></span><br><span class="line">                              <span class="string">" &amp;&amp; is_chassis_resident(\"%s\")"</span>,</span><br><span class="line">                              ETH_ADDR_ARGS(mac),</span><br><span class="line">                              od-&gt;l3dgw_port-&gt;json_key,</span><br><span class="line">                              nat-&gt;logical_port);</span><br><span class="line">                ovn_lflow_add(lflows, od, S_ROUTER_IN_ADMISSION, <span class="number">50</span>,</span><br><span class="line">                              ds_cstr(&amp;match), <span class="string">"next;"</span>);</span><br><span class="line">            &#125;</span><br><span class="line"></span><br><span class="line">            <span class="comment">//ingress 表7,100优先级允许NAT报文通过</span></span><br><span class="line">            <span class="keyword">if</span> (distributed) &#123;</span><br><span class="line">                ds_clear(&amp;match);</span><br><span class="line">                ds_put_format(&amp;match, <span class="string">"ip4.src == %s &amp;&amp; outport == %s"</span>,</span><br><span class="line">                              nat-&gt;logical_ip,</span><br><span class="line">                              od-&gt;l3dgw_port-&gt;json_key);</span><br><span class="line">                ovn_lflow_add(lflows, od, S_ROUTER_IN_GW_REDIRECT, <span class="number">100</span>,</span><br><span class="line">                              ds_cstr(&amp;match), <span class="string">"next;"</span>);</span><br><span class="line">            &#125;</span><br><span class="line"></span><br><span class="line">            <span class="comment">//egress 表2，100优先级如目的IP和EIP相等的话，需要报文clone回注到egress的表0</span></span><br><span class="line">            <span class="keyword">if</span> (od-&gt;l3dgw_port) &#123;</span><br><span class="line">                <span class="comment">//分布式路由</span></span><br><span class="line">                ds_clear(&amp;match);</span><br><span class="line">                ds_put_format(&amp;match, <span class="string">"ip4.dst == %s &amp;&amp; outport == %s"</span>,</span><br><span class="line">                              nat-&gt;external_ip,</span><br><span class="line">                              od-&gt;l3dgw_port-&gt;json_key);</span><br><span class="line">                ds_clear(&amp;actions);</span><br><span class="line">                ds_put_format(&amp;actions,</span><br><span class="line">                              <span class="string">"clone &#123; ct_clear; "</span></span><br><span class="line">                              <span class="string">"inport = outport; outport = \"\"; "</span></span><br><span class="line">                              <span class="string">"flags = 0; flags.loopback = 1; "</span>);</span><br><span class="line">                <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; MFF_N_LOG_REGS; i++) &#123;</span><br><span class="line">                    ds_put_format(&amp;actions, <span class="string">"reg%d = 0; "</span>, i);</span><br><span class="line">                &#125;</span><br><span class="line">                ds_put_format(&amp;actions, REGBIT_EGRESS_LOOPBACK<span class="string">" = 1; "</span></span><br><span class="line">                              <span class="string">"next(pipeline=ingress, table=0); &#125;;"</span>);</span><br><span class="line">                ovn_lflow_add(lflows, od, S_ROUTER_OUT_EGR_LOOP, <span class="number">100</span>,</span><br><span class="line">                              ds_cstr(&amp;match), ds_cstr(&amp;actions));</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="comment">//ingress 表3，110优先级强制SNAT之前DNAT过的报文，网关路由</span></span><br><span class="line">        <span class="keyword">if</span> (dnat_force_snat_ip &amp;&amp; !od-&gt;l3dgw_port) &#123;</span><br><span class="line">            <span class="comment">//如果报文的目的IP是网关路由的IP，那么进行UNSNAT</span></span><br><span class="line">            ds_clear(&amp;match);</span><br><span class="line">            ds_put_format(&amp;match, <span class="string">"ip &amp;&amp; ip4.dst == %s"</span>, dnat_force_snat_ip);</span><br><span class="line">            ovn_lflow_add(lflows, od, S_ROUTER_IN_UNSNAT, <span class="number">110</span>,</span><br><span class="line">                          ds_cstr(&amp;match), <span class="string">"ct_snat; next;"</span>);</span><br><span class="line"></span><br><span class="line">            <span class="comment">//已经DNAT过得报文走这一条，但是SNAT</span></span><br><span class="line">            ds_clear(&amp;match);</span><br><span class="line">            ds_put_format(&amp;match, <span class="string">"flags.force_snat_for_dnat == 1 &amp;&amp; ip"</span>);</span><br><span class="line">            ds_clear(&amp;actions);</span><br><span class="line">            ds_put_format(&amp;actions, <span class="string">"ct_snat(%s);"</span>, dnat_force_snat_ip);</span><br><span class="line">            ovn_lflow_add(lflows, od, S_ROUTER_OUT_SNAT, <span class="number">100</span>,</span><br><span class="line">                          ds_cstr(&amp;match), ds_cstr(&amp;actions));</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">if</span> (lb_force_snat_ip &amp;&amp; !od-&gt;l3dgw_port) &#123;</span><br><span class="line">            <span class="comment">//同上，报文的目的IP是网关路由IP，进行UNSNAT</span></span><br><span class="line">            ds_clear(&amp;match);</span><br><span class="line">            ds_put_format(&amp;match, <span class="string">"ip &amp;&amp; ip4.dst == %s"</span>, lb_force_snat_ip);</span><br><span class="line">            ovn_lflow_add(lflows, od, S_ROUTER_IN_UNSNAT, <span class="number">100</span>,</span><br><span class="line">                          ds_cstr(&amp;match), <span class="string">"ct_snat; next;"</span>);</span><br><span class="line"></span><br><span class="line">            <span class="comment">//有force_snat_for_lb标志的进行SNAT</span></span><br><span class="line">            ds_clear(&amp;match);</span><br><span class="line">            ds_put_format(&amp;match, <span class="string">"flags.force_snat_for_lb == 1 &amp;&amp; ip"</span>);</span><br><span class="line">            ds_clear(&amp;actions);</span><br><span class="line">            ds_put_format(&amp;actions, <span class="string">"ct_snat(%s);"</span>, lb_force_snat_ip);</span><br><span class="line">            ovn_lflow_add(lflows, od, S_ROUTER_OUT_SNAT, <span class="number">100</span>,</span><br><span class="line">                          ds_cstr(&amp;match), ds_cstr(&amp;actions));</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">if</span> (!od-&gt;l3dgw_port) &#123;</span><br><span class="line">            <span class="comment">//网关路由，重新循环每个报文到DNAT区域</span></span><br><span class="line">            <span class="comment">//需要UNDNAT的报文都会进行UNDNAT，理想情况下，可以在egress完成</span></span><br><span class="line">            <span class="comment">//但是由于网关路由器没有任何关于将源IP地址作为IP路由的EIP的特性</span></span><br><span class="line">            <span class="comment">//所以我们可以在此处进行操作，从而省去了以后的一次重新循环</span></span><br><span class="line">            <span class="comment">//任何通过SNAT区域的报文都会自动重新循环</span></span><br><span class="line">            <span class="comment">//来得到openflow pipeline的路由需要的新目的IP</span></span><br><span class="line">            ovn_lflow_add(lflows, od, S_ROUTER_IN_DNAT, <span class="number">50</span>,</span><br><span class="line">                              <span class="string">"ip4"</span>, <span class="string">"flags.loopback = 1; ct_dnat;"</span>);</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            <span class="comment">//分布式路由的NAT，向ingress中没有NAT规则的IP路由表、ARP处理表、网关重定向添加流表</span></span><br><span class="line">            <span class="comment">//ingress的表5 300优先级添加流表</span></span><br><span class="line">            ovn_lflow_add(lflows, od, S_ROUTER_IN_IP_ROUTING, <span class="number">300</span>,</span><br><span class="line">                          REGBIT_NAT_REDIRECT<span class="string">" == 1"</span>, <span class="string">"ip.ttl--; next;"</span>);</span><br><span class="line"></span><br><span class="line">            <span class="comment">//ingress的表5 200优先级添加流表，修改目的MAC位分布式网关端口的地址</span></span><br><span class="line">            ds_clear(&amp;actions);</span><br><span class="line">            ds_put_format(&amp;actions, <span class="string">"eth.dst = %s; next;"</span>,</span><br><span class="line">                          od-&gt;l3dgw_port-&gt;lrp_networks.ea_s);</span><br><span class="line">            ovn_lflow_add(lflows, od, S_ROUTER_IN_ARP_RESOLVE, <span class="number">200</span>,</span><br><span class="line">                          REGBIT_NAT_REDIRECT<span class="string">" == 1"</span>, ds_cstr(&amp;actions));</span><br><span class="line"></span><br><span class="line">            <span class="comment">//ingress的表7 200优先级添加流表</span></span><br><span class="line">            ds_clear(&amp;actions);</span><br><span class="line">            ds_put_format(&amp;actions, <span class="string">"outport = %s; next;"</span>,</span><br><span class="line">                          od-&gt;l3redirect_port-&gt;json_key);</span><br><span class="line">            ovn_lflow_add(lflows, od, S_ROUTER_IN_GW_REDIRECT, <span class="number">200</span>,</span><br><span class="line">                          REGBIT_NAT_REDIRECT<span class="string">" == 1"</span>, ds_cstr(&amp;actions));</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="comment">//处理所有需要重组或者conntrack的IP的设置</span></span><br><span class="line">        <span class="class"><span class="keyword">struct</span> <span class="title">sset</span> <span class="title">all_ips</span> = <span class="title">SSET_INITIALIZER</span>(&amp;<span class="title">all_ips</span>);</span></span><br><span class="line"></span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; od-&gt;nbr-&gt;n_load_balancer; i++) &#123;</span><br><span class="line">            <span class="class"><span class="keyword">struct</span> <span class="title">nbrec_load_balancer</span> *<span class="title">lb</span> = <span class="title">od</span>-&gt;<span class="title">nbr</span>-&gt;<span class="title">load_balancer</span>[<span class="title">i</span>];</span></span><br><span class="line">            <span class="class"><span class="keyword">struct</span> <span class="title">smap</span> *<span class="title">vips</span> = &amp;<span class="title">lb</span>-&gt;<span class="title">vips</span>;</span></span><br><span class="line">            <span class="class"><span class="keyword">struct</span> <span class="title">smap_node</span> *<span class="title">node</span>;</span></span><br><span class="line"></span><br><span class="line">            SMAP_FOR_EACH (node, vips) &#123;</span><br><span class="line">                <span class="keyword">uint16_t</span> port = <span class="number">0</span>;</span><br><span class="line"></span><br><span class="line">                <span class="keyword">char</span> *ip_address = <span class="literal">NULL</span>;</span><br><span class="line">                ip_address_and_port_from_lb_key(node-&gt;key, &amp;ip_address, &amp;port);</span><br><span class="line">                <span class="keyword">if</span> (!ip_address) &#123;</span><br><span class="line">                    <span class="keyword">continue</span>;</span><br><span class="line">                &#125;</span><br><span class="line"></span><br><span class="line">                <span class="keyword">if</span> (!sset_contains(&amp;all_ips, ip_address)) &#123;</span><br><span class="line">                    sset_add(&amp;all_ips, ip_address);</span><br><span class="line">                &#125;</span><br><span class="line"></span><br><span class="line">                <span class="comment">//ingress 表4 DNAT中的LB添加高级的规则，120和110优先级</span></span><br><span class="line">                <span class="comment">//每个匹配项，我们通过add_router_lb_flow()添加两条流表</span></span><br><span class="line">                <span class="comment">//一条流表为ct.new添加操作ct_lb($targets)</span></span><br><span class="line">                <span class="comment">//另一条流表为ct.est添加操作ct_dnat;</span></span><br><span class="line">                ds_clear(&amp;actions);</span><br><span class="line">                ds_put_format(&amp;actions, <span class="string">"ct_lb(%s);"</span>, node-&gt;value);</span><br><span class="line"></span><br><span class="line">                ds_clear(&amp;match);</span><br><span class="line">                ds_put_format(&amp;match, <span class="string">"ip &amp;&amp; ip4.dst == %s"</span>,</span><br><span class="line">                              ip_address);</span><br><span class="line">                <span class="built_in">free</span>(ip_address);</span><br><span class="line"></span><br><span class="line">                <span class="keyword">if</span> (port) &#123;</span><br><span class="line">                    <span class="keyword">if</span> (lb-&gt;protocol &amp;&amp; !<span class="built_in">strcmp</span>(lb-&gt;protocol, <span class="string">"udp"</span>)) &#123;</span><br><span class="line">                        ds_put_format(&amp;match, <span class="string">" &amp;&amp; udp &amp;&amp; udp.dst == %d"</span>,</span><br><span class="line">                                      port);</span><br><span class="line">                    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                        ds_put_format(&amp;match, <span class="string">" &amp;&amp; tcp &amp;&amp; tcp.dst == %d"</span>,</span><br><span class="line">                                      port);</span><br><span class="line">                    &#125;</span><br><span class="line">                    add_router_lb_flow(lflows, od, &amp;match, &amp;actions, <span class="number">120</span>,</span><br><span class="line">                                       lb_force_snat_ip);</span><br><span class="line">                &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                    add_router_lb_flow(lflows, od, &amp;match, &amp;actions, <span class="number">110</span>,</span><br><span class="line">                                       lb_force_snat_ip);</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="comment">//如果有LB规则，我们应该将报文发送到重组和conntrack中</span></span><br><span class="line">        <span class="comment">//有了conntrack，我们可以只从组里的新连接去设置DNAT IP</span></span><br><span class="line">        <span class="comment">//如果LB规则中有L4的端口，我们需要重组进行匹配L4端口</span></span><br><span class="line">        <span class="keyword">const</span> <span class="keyword">char</span> *ip_address;</span><br><span class="line">        SSET_FOR_EACH(ip_address, &amp;all_ips) &#123;</span><br><span class="line">            ds_clear(&amp;match);</span><br><span class="line">            ds_put_format(&amp;match, <span class="string">"ip &amp;&amp; ip4.dst == %s"</span>, ip_address);</span><br><span class="line">            ovn_lflow_add(lflows, od, S_ROUTER_IN_DEFRAG,</span><br><span class="line">                          <span class="number">100</span>, ds_cstr(&amp;match), <span class="string">"ct_next;"</span>);</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        sset_destroy(&amp;all_ips);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">//ingress 表5 该表设置出口为正确的出口，并且源MAC修改为出口的MAC</span></span><br><span class="line">    <span class="comment">//下一跳的IP从reg0中拿到，并且下一条表处理ARP resolution</span></span><br><span class="line">    HMAP_FOR_EACH (op, key_node, ports) &#123;</span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; op-&gt;lrp_networks.n_ipv4_addrs; i++) &#123;</span><br><span class="line">            add_route(lflows, op, op-&gt;lrp_networks.ipv4_addrs[i].addr_s,</span><br><span class="line">                      op-&gt;lrp_networks.ipv4_addrs[i].network_s,</span><br><span class="line">                      op-&gt;lrp_networks.ipv4_addrs[i].plen, <span class="literal">NULL</span>, <span class="literal">NULL</span>);</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; op-&gt;lrp_networks.n_ipv6_addrs; i++) &#123;</span><br><span class="line">            add_route(lflows, op, op-&gt;lrp_networks.ipv6_addrs[i].addr_s,</span><br><span class="line">                      op-&gt;lrp_networks.ipv6_addrs[i].network_s,</span><br><span class="line">                      op-&gt;lrp_networks.ipv6_addrs[i].plen, <span class="literal">NULL</span>, <span class="literal">NULL</span>);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">//将静态路由转换为流表</span></span><br><span class="line">    HMAP_FOR_EACH (od, key_node, datapaths) &#123;</span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; od-&gt;nbr-&gt;n_static_routes; i++) &#123;</span><br><span class="line">            <span class="keyword">const</span> <span class="class"><span class="keyword">struct</span> <span class="title">nbrec_logical_router_static_route</span> *<span class="title">route</span>;</span></span><br><span class="line"></span><br><span class="line">            route = od-&gt;nbr-&gt;static_routes[i];</span><br><span class="line">            build_static_route_flow(lflows, od, ports, route);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">//ingress 表6</span></span><br><span class="line">    <span class="comment">//下一跳的IP地址存储在reg0，该表处理reg0中的IP设置到出口并且将MAC设置到报文目的MAC</span></span><br><span class="line">    HMAP_FOR_EACH (op, key_node, ports) &#123;</span><br><span class="line">        <span class="keyword">if</span> (op-&gt;nbrp) &#123;</span><br><span class="line">            <span class="comment">//当前状况是逻辑路由端口，当下一跳IP(存于reg0中)匹配该路由端口时，</span></span><br><span class="line">            <span class="comment">//流表出口设置为这个逻辑端口，并且将该口的MAC设置为报文的目的MAC</span></span><br><span class="line">            <span class="comment">//报文依然在对端的逻辑pipeline中，所以应当匹配对端的出口</span></span><br><span class="line">            <span class="keyword">if</span> (op-&gt;peer &amp;&amp; op-&gt;nbrp-&gt;peer) &#123;</span><br><span class="line">                <span class="keyword">if</span> (op-&gt;lrp_networks.n_ipv4_addrs) &#123;</span><br><span class="line">                    ds_clear(&amp;match);</span><br><span class="line">                    ds_put_format(&amp;match, <span class="string">"outport == %s &amp;&amp; reg0 == "</span>,</span><br><span class="line">                                  op-&gt;peer-&gt;json_key);</span><br><span class="line">                    op_put_v4_networks(&amp;match, op, <span class="literal">false</span>);</span><br><span class="line"></span><br><span class="line">                    ds_clear(&amp;actions);</span><br><span class="line">                    ds_put_format(&amp;actions, <span class="string">"eth.dst = %s; next;"</span>,</span><br><span class="line">                                  op-&gt;lrp_networks.ea_s);</span><br><span class="line">                    ovn_lflow_add(lflows, op-&gt;peer-&gt;od, S_ROUTER_IN_ARP_RESOLVE,</span><br><span class="line">                                  <span class="number">100</span>, ds_cstr(&amp;match), ds_cstr(&amp;actions));</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125; <span class="keyword">else</span> <span class="keyword">if</span> (op-&gt;od-&gt;n_router_ports &amp;&amp; <span class="built_in">strcmp</span>(op-&gt;nbsp-&gt;type, <span class="string">"router"</span>)) &#123;</span><br><span class="line">            <span class="comment">//当前状况是逻辑交换的端口，连接了一个VM或者容器</span></span><br><span class="line">            <span class="comment">//解析里面的地址，为每个地址遍历连接到逻辑交换的所有路由端口</span></span><br><span class="line">            <span class="comment">//如果地址从路由端口科大，添加ARP表到路由的pipeline</span></span><br><span class="line"></span><br><span class="line">            <span class="keyword">for</span> (<span class="keyword">size_t</span> i = <span class="number">0</span>; i &lt; op-&gt;n_lsp_addrs; i++) &#123;</span><br><span class="line">                <span class="keyword">const</span> <span class="keyword">char</span> *ea_s = op-&gt;lsp_addrs[i].ea_s;</span><br><span class="line">                <span class="keyword">for</span> (<span class="keyword">size_t</span> j = <span class="number">0</span>; j &lt; op-&gt;lsp_addrs[i].n_ipv4_addrs; j++) &#123;</span><br><span class="line">                    <span class="keyword">const</span> <span class="keyword">char</span> *ip_s = op-&gt;lsp_addrs[i].ipv4_addrs[j].addr_s;</span><br><span class="line">                    <span class="keyword">for</span> (<span class="keyword">size_t</span> k = <span class="number">0</span>; k &lt; op-&gt;od-&gt;n_router_ports; k++) &#123;</span><br><span class="line">                        <span class="keyword">const</span> <span class="keyword">char</span> *peer_name = smap_get(</span><br><span class="line">                            &amp;op-&gt;od-&gt;router_ports[k]-&gt;nbsp-&gt;options,</span><br><span class="line">                            <span class="string">"router-port"</span>);</span><br><span class="line">                        ds_clear(&amp;match);</span><br><span class="line">                        ds_put_format(&amp;match, <span class="string">"outport == %s &amp;&amp; reg0 == %s"</span>,</span><br><span class="line">                                      peer-&gt;json_key, ip_s);</span><br><span class="line"></span><br><span class="line">                        ds_clear(&amp;actions);</span><br><span class="line">                        ds_put_format(&amp;actions, <span class="string">"eth.dst = %s; next;"</span>, ea_s);</span><br><span class="line">                        ovn_lflow_add(lflows, peer-&gt;od,</span><br><span class="line">                                      S_ROUTER_IN_ARP_RESOLVE, <span class="number">100</span>,</span><br><span class="line">                                      ds_cstr(&amp;match), ds_cstr(&amp;actions));</span><br><span class="line">                    &#125;</span><br><span class="line">                &#125;</span><br><span class="line"></span><br><span class="line">                <span class="keyword">for</span> (<span class="keyword">size_t</span> j = <span class="number">0</span>; j &lt; op-&gt;lsp_addrs[i].n_ipv6_addrs; j++) &#123;</span><br><span class="line">                    <span class="keyword">const</span> <span class="keyword">char</span> *ip_s = op-&gt;lsp_addrs[i].ipv6_addrs[j].addr_s;</span><br><span class="line">                    <span class="keyword">for</span> (<span class="keyword">size_t</span> k = <span class="number">0</span>; k &lt; op-&gt;od-&gt;n_router_ports; k++) &#123;</span><br><span class="line">                        <span class="keyword">const</span> <span class="keyword">char</span> *peer_name = smap_get(</span><br><span class="line">                            &amp;op-&gt;od-&gt;router_ports[k]-&gt;nbsp-&gt;options,</span><br><span class="line">                            <span class="string">"router-port"</span>);</span><br><span class="line">                        ds_clear(&amp;match);</span><br><span class="line">                        ds_put_format(&amp;match, <span class="string">"outport == %s &amp;&amp; xxreg0 == %s"</span>,</span><br><span class="line">                                      peer-&gt;json_key, ip_s);</span><br><span class="line"></span><br><span class="line">                        ds_clear(&amp;actions);</span><br><span class="line">                        ds_put_format(&amp;actions, <span class="string">"eth.dst = %s; next;"</span>, ea_s);</span><br><span class="line">                        ovn_lflow_add(lflows, peer-&gt;od,</span><br><span class="line">                                      S_ROUTER_IN_ARP_RESOLVE, <span class="number">100</span>,</span><br><span class="line">                                      ds_cstr(&amp;match), ds_cstr(&amp;actions));</span><br><span class="line">                    &#125;</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125; <span class="keyword">else</span> <span class="keyword">if</span> (!<span class="built_in">strcmp</span>(op-&gt;nbsp-&gt;type, <span class="string">"router"</span>)) &#123;</span><br><span class="line">            <span class="comment">//当前是连接路由的逻辑交换端口</span></span><br><span class="line">            <span class="comment">//该交换端口的对端是路由端口</span></span><br><span class="line">            <span class="comment">//我们需要添加逻辑流表，能够对所有连接到该交换机的路由端口添加ARP信息</span></span><br><span class="line">            <span class="keyword">const</span> <span class="keyword">char</span> *peer_name = smap_get(&amp;op-&gt;nbsp-&gt;options,</span><br><span class="line">                                             <span class="string">"router-port"</span>);</span><br><span class="line">            <span class="class"><span class="keyword">struct</span> <span class="title">ovn_port</span> *<span class="title">peer</span> = <span class="title">ovn_port_find</span>(<span class="title">ports</span>, <span class="title">peer_name</span>);</span></span><br><span class="line">            <span class="keyword">for</span> (<span class="keyword">size_t</span> i = <span class="number">0</span>; i &lt; op-&gt;od-&gt;n_router_ports; i++) &#123;</span><br><span class="line">                <span class="keyword">const</span> <span class="keyword">char</span> *router_port_name = smap_get(</span><br><span class="line">                                    &amp;op-&gt;od-&gt;router_ports[i]-&gt;nbsp-&gt;options,</span><br><span class="line">                                    <span class="string">"router-port"</span>);</span><br><span class="line">                <span class="class"><span class="keyword">struct</span> <span class="title">ovn_port</span> *<span class="title">router_port</span> = <span class="title">ovn_port_find</span>(<span class="title">ports</span>,</span></span><br><span class="line"><span class="class">                                                             <span class="title">router_port_name</span>);</span></span><br><span class="line">                <span class="keyword">if</span> (router_port-&gt;lrp_networks.n_ipv4_addrs) &#123;</span><br><span class="line">                    ds_clear(&amp;match);</span><br><span class="line">                    ds_put_format(&amp;match, <span class="string">"outport == %s &amp;&amp; reg0 == "</span>,</span><br><span class="line">                                  peer-&gt;json_key);</span><br><span class="line">                    op_put_v4_networks(&amp;match, router_port, <span class="literal">false</span>);</span><br><span class="line"></span><br><span class="line">                    ds_clear(&amp;actions);</span><br><span class="line">                    ds_put_format(&amp;actions, <span class="string">"eth.dst = %s; next;"</span>,</span><br><span class="line">                                              router_port-&gt;lrp_networks.ea_s);</span><br><span class="line">                    ovn_lflow_add(lflows, peer-&gt;od, S_ROUTER_IN_ARP_RESOLVE,</span><br><span class="line">                                  <span class="number">100</span>, ds_cstr(&amp;match), ds_cstr(&amp;actions));</span><br><span class="line">                &#125;</span><br><span class="line"></span><br><span class="line">                <span class="keyword">if</span> (router_port-&gt;lrp_networks.n_ipv6_addrs) &#123;</span><br><span class="line">                    ds_clear(&amp;match);</span><br><span class="line">                    ds_put_format(&amp;match, <span class="string">"outport == %s &amp;&amp; xxreg0 == "</span>,</span><br><span class="line">                                  peer-&gt;json_key);</span><br><span class="line">                    op_put_v6_networks(&amp;match, router_port);</span><br><span class="line"></span><br><span class="line">                    ds_clear(&amp;actions);</span><br><span class="line">                    ds_put_format(&amp;actions, <span class="string">"eth.dst = %s; next;"</span>,</span><br><span class="line">                                  router_port-&gt;lrp_networks.ea_s);</span><br><span class="line">                    ovn_lflow_add(lflows, peer-&gt;od, S_ROUTER_IN_ARP_RESOLVE,</span><br><span class="line">                                  <span class="number">100</span>, ds_cstr(&amp;match), ds_cstr(&amp;actions));</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    HMAP_FOR_EACH (od, key_node, datapaths) &#123;</span><br><span class="line">        ovn_lflow_add(lflows, od, S_ROUTER_IN_ARP_RESOLVE, <span class="number">0</span>, <span class="string">"ip4"</span>,</span><br><span class="line">                      <span class="string">"get_arp(outport, reg0); next;"</span>);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">//ingress 表7 分布式路由中，出口和l3dgw_port相等时</span></span><br><span class="line">    <span class="comment">//这个表会将一个子网的流量转发到l3redirect_port</span></span><br><span class="line">    HMAP_FOR_EACH (od, key_node, datapaths) &#123;</span><br><span class="line">        <span class="keyword">if</span> (od-&gt;l3dgw_port &amp;&amp; od-&gt;l3redirect_port) &#123;</span><br><span class="line">            <span class="comment">//当流量的出口等于l3dgw_port，如果报文不匹配更高级的重定向规则</span></span><br><span class="line">            <span class="comment">//那么流量将重定向到l3dgw_port的中心实例</span></span><br><span class="line">            ds_clear(&amp;match);</span><br><span class="line">            ds_put_format(&amp;match, <span class="string">"outport == %s"</span>,</span><br><span class="line">                          od-&gt;l3dgw_port-&gt;json_key);</span><br><span class="line">            ds_clear(&amp;actions);</span><br><span class="line">            ds_put_format(&amp;actions, <span class="string">"outport = %s; next;"</span>,</span><br><span class="line">                          od-&gt;l3redirect_port-&gt;json_key);</span><br><span class="line">            ovn_lflow_add(lflows, od, S_ROUTER_IN_GW_REDIRECT, <span class="number">50</span>,</span><br><span class="line">                          ds_cstr(&amp;match), ds_cstr(&amp;actions));</span><br><span class="line"></span><br><span class="line">            <span class="comment">//如果目的MAC已经处理了，则重定向到l3dgw_port的中心实例</span></span><br><span class="line">            <span class="comment">//这些流量在进行重定向到中心实例之前，将被ingress表中的ARP request替代</span></span><br><span class="line">            ds_put_format(&amp;match, <span class="string">" &amp;&amp; eth.dst == 00:00:00:00:00:00"</span>);</span><br><span class="line">            ovn_lflow_add(lflows, od, S_ROUTER_IN_GW_REDIRECT, <span class="number">150</span>,</span><br><span class="line">                          ds_cstr(&amp;match), ds_cstr(&amp;actions));</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="comment">//0优先级默认是转发</span></span><br><span class="line">        ovn_lflow_add(lflows, od, S_ROUTER_IN_GW_REDIRECT, <span class="number">0</span>, <span class="string">"1"</span>, <span class="string">"next;"</span>);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">//ingress 表8 100优先级用来发送ARP Request</span></span><br><span class="line">    <span class="comment">//主要是目的MAC修改为广播、源IP从reg1取，目标IP从reg0取、操作为request，最后发送</span></span><br><span class="line">    <span class="comment">//0优先级表示目的MAC地址可以处理，直接发送</span></span><br><span class="line">    HMAP_FOR_EACH (od, key_node, datapaths) &#123;</span><br><span class="line">        ovn_lflow_add(lflows, od, S_ROUTER_IN_ARP_REQUEST, <span class="number">100</span>,</span><br><span class="line">                      <span class="string">"eth.dst == 00:00:00:00:00:00"</span>,</span><br><span class="line">                      <span class="string">"arp &#123; "</span></span><br><span class="line">                      <span class="string">"eth.dst = ff:ff:ff:ff:ff:ff; "</span></span><br><span class="line">                      <span class="string">"arp.spa = reg1; "</span></span><br><span class="line">                      <span class="string">"arp.tpa = reg0; "</span></span><br><span class="line">                      <span class="string">"arp.op = 1; "</span> <span class="comment">/* ARP request */</span></span><br><span class="line">                      <span class="string">"output; "</span></span><br><span class="line">                      <span class="string">"&#125;;"</span>);</span><br><span class="line">        ovn_lflow_add(lflows, od, S_ROUTER_IN_ARP_REQUEST, <span class="number">0</span>, <span class="string">"1"</span>, <span class="string">"output;"</span>);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">//egress 表3 100优先级直接匹配逻辑出口，执行发送</span></span><br><span class="line">    HMAP_FOR_EACH (op, key_node, ports) &#123;</span><br><span class="line">        ds_clear(&amp;match);</span><br><span class="line">        ds_put_format(&amp;match, <span class="string">"outport == %s"</span>, op-&gt;json_key);</span><br><span class="line">        ovn_lflow_add(lflows, op-&gt;od, S_ROUTER_OUT_DELIVERY, <span class="number">100</span>,</span><br><span class="line">                      ds_cstr(&amp;match), <span class="string">"output;"</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></div><div></div><footer class="post-footer"><div class="post-nav"><div class="post-nav-next post-nav-item"><a href="/2017/02/26/SDN/OVN/2017-02-26-ovn-flows/" rel="next" title="OVN Logical Flows to Openflows"><i class="fa fa-chevron-left"></i> OVN Logical Flows to Openflows</a></div><div class="post-nav-prev post-nav-item"> <a href="/2017/03/05/SDN/OVS/2017-03-05-flow-translate/" rel="prev" title="OpenvSwitch 流表转换">OpenvSwitch 流表转换<i class="fa fa-chevron-right"></i></a></div></div></footer></div></article><div class="post-copyright"><p><span>注意:</span>所有文章非特别说明皆为原创。为保证信息与源同步，转载时请务必注明文章出处！谢谢合作 :-)</p><p> <span>原始链接:</span><a class="post-url" href="/2017/03/04/SDN/OVN/2017-03-04-ovn-northd/" title="OVN Northd服务工作">http://zhaozhanxu.com/2017/03/04/SDN/OVN/2017-03-04-ovn-northd/</a><span class="copy-path" data-clipboard-text="原文: http://zhaozhanxu.com/2017/03/04/SDN/OVN/2017-03-04-ovn-northd/　　作者: 赵占旭" title="点击复制文章链接"><i class="fa fa-clipboard"></i></span><script src="/js/clipboard.min.js"></script><script>var clipboard=new Clipboard(".copy-path")</script></p><p> <span>许可协议:</span><i class="fa fa-creative-commons"></i> <a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/4.0/cn" title="中国大陆 (CC BY-NC-SA 4.0 CN)" target="_blank">"署名-非商用-相同方式共享 4.0"</a> 转载请保留原文链接及作者。</p></div></div></div><div class="comments" id="comments"></div></div><div class="sidebar-toggle"><div class="sidebar-toggle-line-wrap"><span class="sidebar-toggle-line sidebar-toggle-line-first"></span><span class="sidebar-toggle-line sidebar-toggle-line-middle"></span><span class="sidebar-toggle-line sidebar-toggle-line-last"></span></div></div><aside id="sidebar" class="sidebar"><div class="sidebar-inner"><section class="site-overview sidebar-panel sidebar-panel-active"><div class="site-author motion-element" itemprop="author" itemscope itemtype="http://schema.org/Person"> <a href="/about"><img class="site-author-image" itemprop="image" src="/images/public/me.jpg" alt="赵占旭"><p class="site-author-name" itemprop="name">赵占旭</p><p class="site-description motion-element" itemprop="description"></p></a></div><nav class="site-state motion-element"><div class="site-state-item site-state-posts"> <a href="/archives"><span class="site-state-item-count">61</span> <span class="site-state-item-name">posts</span></a></div><div class="site-state-item site-state-categories"> <a href="/categories"><span class="site-state-item-count">7</span> <span class="site-state-item-name">categories</span></a></div><div class="site-state-item site-state-tags"> <a href="/tags"><span class="site-state-item-count">14</span> <span class="site-state-item-name">tags</span></a></div></nav><div class="feed-link motion-element"><a href="/atom.xml" rel="alternate"><i class="fa fa-rss"></i> RSS</a></div><div class="links-of-author motion-element"><span class="links-of-author-item"><a href="mailto:zhaozhanxu@163.com" target="_blank" title="Mail"><i class="fa fa-fw fa-envelope"></i> Mail</a></span><span class="links-of-author-item"><a href="https://github.com/zhaozhanxu" target="_blank" title="GitHub"><i class="fa fa-fw fa-github"></i> GitHub</a></span><span class="links-of-author-item"><a href="https://www.linkedin.com/in/zhaozhanxu" target="_blank" title="LinkedIn"><i class="fa fa-fw fa-linkedin"></i> LinkedIn</a></span><span class="links-of-author-item"><a href="https://twitter.com/zhaozhanxu" target="_blank" title="Twitter"><i class="fa fa-fw fa-twitter"></i> Twitter</a></span><span class="links-of-author-item"><a href="/about/" target="_blank" title="Wechat"><i class="fa fa-fw fa-wechat"></i> Wechat</a></span><span class="links-of-author-item"><a href="/about/" target="_blank" title="QQ"><i class="fa fa-fw fa-qq"></i> QQ</a></span></div><div class="links-of-blogroll motion-element links-of-blogroll-inline"><div class="links-of-blogroll-title"><i class="fa fa-fw fa-address-book"></i> 基情链接</div><ul class="links-of-blogroll-list"><li class="links-of-blogroll-item"> <a href="http://blog.csdn.net/jqh9804" title="呆子辉" target="_blank">呆子辉</a></li></ul></div></section></div></aside></div></main><footer id="footer" class="footer"><div class="footer-inner"><div class="copyright"> &copy; 2016 - <span itemprop="copyrightYear">2017</span><span class="with-love"><i class="fa fa-heart"></i></span> <span class="author" itemprop="copyrightHolder">赵占旭</span></div><div class="powered-by"> Powered by <a class="theme-link" href="https://hexo.io">Hexo</a></div><div class="theme-info"> Theme - <a class="theme-link" href="https://github.com/iissnan/hexo-theme-next">NexT</a></div><div class="busuanzi-count"><script async src="https://dn-lbstatics.qbox.me/busuanzi/2.3/busuanzi.pure.mini.js"></script><span class="site-uv"><i class="fa fa-user"></i><span class="busuanzi-value" id="busuanzi_value_site_uv"></span></span><span class="site-pv"><i class="fa fa-eye"></i><span class="busuanzi-value" id="busuanzi_value_page_pv"></span></span></div></div></footer><div class="back-to-top"><i class="fa fa-arrow-up"></i></div></div><script type="text/javascript">"[object Function]"!==Object.prototype.toString.call(window.Promise)&&(window.Promise=null)</script><script type="text/javascript" src="/lib/jquery/index.js?v=2.1.3"></script><script type="text/javascript" src="/lib/fastclick/lib/fastclick.min.js?v=1.0.6"></script><script type="text/javascript" src="/lib/jquery_lazyload/jquery.lazyload.js?v=1.9.7"></script><script type="text/javascript" src="/lib/velocity/velocity.min.js?v=1.2.1"></script><script type="text/javascript" src="/lib/velocity/velocity.ui.min.js?v=1.2.1"></script><script type="text/javascript" src="/lib/fancybox/source/jquery.fancybox.pack.js?v=2.1.5"></script><script type="text/javascript" src="/lib/canvas-nest/canvas-nest.min.js"></script><script type="text/javascript" src="/js/src/utils.js?v=5.1.0"></script><script type="text/javascript" src="/js/src/motion.js?v=5.1.0"></script><script type="text/javascript" src="/js/src/affix.js?v=5.1.0"></script><script type="text/javascript" src="/js/src/schemes/pisces.js?v=5.1.0"></script><script type="text/javascript" src="/js/src/scrollspy.js?v=5.1.0"></script><script type="text/javascript" src="/js/src/post-details.js?v=5.1.0"></script><script type="text/javascript" src="/js/src/bootstrap.js?v=5.1.0"></script><script type="text/javascript">function proceedsearch(){$("body").append('<div class="popoverlay">').css("overflow","hidden"),$(".popup").toggle()}var isfetched=!1,search_path="search.xml";0==search_path.length&&(search_path="search.xml");var path="/"+search_path,searchFunc=function(e,t,a){"use strict";$.ajax({url:e,dataType:"xml",async:!0,success:function(e){isfetched=!0,$(".popup").detach().appendTo(".header-inner");var r=$("entry",e).map(function(){return{title:$("title",this).text(),content:$("content",this).text(),url:$("url",this).text()}}).get(),c=document.getElementById(t),n=document.getElementById(a);c.addEventListener("input",function(){var e=0,t='<ul class="search-result-list">',a=this.value.trim().toLowerCase().split(/[\s\-]+/);n.innerHTML="",this.value.trim().length>1&&r.forEach(function(r){var c=!1,n=r.title.trim().toLowerCase(),s=r.content.trim().replace(/<[^>]+>/g,"").toLowerCase(),o=decodeURIComponent(r.url),i=-1,l=-1,p=-1;if(""!=n&&a.forEach(function(e,t){i=n.indexOf(e),l=s.indexOf(e),(i>=0||l>=0)&&(c=!0,0==t&&(p=l))}),c){e+=1,t+="<li><a href='"+o+"' class='search-result-title'>"+n+"</a>";var h=r.content.trim().replace(/<[^>]+>/g,"");if(p>=0){var u=p-20,d=p+80;u<0&&(u=0),0==u&&(d=50),d>h.length&&(d=h.length);var f=h.substring(u,d);a.forEach(function(e){var t=new RegExp(e,"gi");f=f.replace(t,'<b class="search-keyword">'+e+"</b>")}),t+='<p class="search-result">'+f+"...</p>"}t+="</li>"}}),t+="</ul>",0==e&&(t='<div id="no-result"><i class="fa fa-frown-o fa-5x" /></div>'),""==a&&(t='<div id="no-result"><i class="fa fa-search fa-5x" /></div>'),n.innerHTML=t}),proceedsearch()}})};$(".popup-trigger").click(function(e){e.stopPropagation(),0==isfetched?searchFunc(path,"local-search-input","local-search-result"):proceedsearch()}),$(".popup-btn-close").click(function(e){$(".popup").hide(),$(".popoverlay").remove(),$("body").css("overflow","")}),$(".popup").click(function(e){e.stopPropagation()})</script><script>!function(){var t=document.createElement("script"),e=window.location.protocol.split(":")[0];t.src="https"===e?"https://zz.bdstatic.com/linksubmit/push.js":"http://push.zhanzhang.baidu.com/push.js";var s=document.getElementsByTagName("script")[0];s.parentNode.insertBefore(t,s)}()</script></body></html>